Revert bad merge from vhdl branch

This commit is contained in:
Stephen Williams 2010-10-02 11:02:27 -07:00
parent 7f2cb6afcd
commit ec49f10e2d
83 changed files with 1254 additions and 1140 deletions

View File

@ -30,7 +30,7 @@ SHELL = /bin/sh
# The "suffix" is used as an installation suffix. It modifies certain # The "suffix" is used as an installation suffix. It modifies certain
# key install paths/files such that a build and install of Icarus Verilog # key install paths/files such that a build and install of Icarus Verilog
# with the same $(prefix) but a different $(suffix) will not interfere. # with the same $(prefix) but a different $(suffix) will not interfere.
# The normal configuratin leaves suffix empty # The normal configuration leaves suffix empty
suffix = @install_suffix@ suffix = @install_suffix@
prefix = @prefix@ prefix = @prefix@
@ -240,7 +240,7 @@ iverilog-vpi.man: $(srcdir)/iverilog-vpi.man.in version.exe
tail -n +2 $(srcdir)/iverilog-vpi.man.in >> $@ tail -n +2 $(srcdir)/iverilog-vpi.man.in >> $@
iverilog-vpi.ps: iverilog-vpi.man iverilog-vpi.ps: iverilog-vpi.man
$(MAN) -t iverilog-vpi.man > iverilog-vpi.ps $(MAN) -t ./iverilog-vpi.man > iverilog-vpi.ps
iverilog-vpi.pdf: iverilog-vpi.ps iverilog-vpi.pdf: iverilog-vpi.ps
$(PS2PDF) iverilog-vpi.ps iverilog-vpi.pdf $(PS2PDF) iverilog-vpi.ps iverilog-vpi.pdf

View File

@ -1,7 +1,7 @@
#ifndef __discipline_H #ifndef __discipline_H
#define __discipline_H #define __discipline_H
/* /*
* Copyright (c) 2008 Stephen Williams (steve@icarus.com) * Copyright (c) 2008-2010 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -55,8 +55,8 @@ class ivl_discipline_s : public LineInfo {
perm_string name() const { return name_; } perm_string name() const { return name_; }
ivl_dis_domain_t domain() const { return domain_; } ivl_dis_domain_t domain() const { return domain_; }
const ivl_nature_t potential() const { return potential_; } ivl_nature_t potential() const { return potential_; }
const ivl_nature_t flow() const { return flow_; } ivl_nature_t flow() const { return flow_; }
private: private:
perm_string name_; perm_string name_;

View File

@ -89,7 +89,7 @@ iverilog.man: $(srcdir)/iverilog.man.in ../version.exe
tail -n +2 $(srcdir)/iverilog.man.in >> $@ tail -n +2 $(srcdir)/iverilog.man.in >> $@
iverilog.ps: iverilog.man iverilog.ps: iverilog.man
$(MAN) -t iverilog.man > iverilog.ps $(MAN) -t ./iverilog.man > iverilog.ps
iverilog.pdf: iverilog.ps iverilog.pdf: iverilog.ps
$(PS2PDF) iverilog.ps iverilog.pdf $(PS2PDF) iverilog.ps iverilog.pdf

View File

@ -40,10 +40,10 @@ extern void process_include_dir(const char*name);
/* Add a new -D define. */ /* Add a new -D define. */
extern void process_define(const char*name); extern void process_define(const char*name);
/* Add a new parameter definition */ /* Add a new parameter definition */
extern void process_parameter(const char*name); extern void process_parameter(const char*name);
/* Set the default timescale for the simulator. */ /* Set the default timescale for the simulator. */
extern void process_timescale(const char*ts_string); extern void process_timescale(const char*ts_string);

View File

@ -64,7 +64,7 @@ Verilog source for use by other compilers.
.B -g1995\fI|\fP-g2001\fI|\fP-g2001-noconfig\fI|\fP-g2005\fI|\fP-g2009 .B -g1995\fI|\fP-g2001\fI|\fP-g2001-noconfig\fI|\fP-g2005\fI|\fP-g2009
Select the Verilog language \fIgeneration\fP to support in the Select the Verilog language \fIgeneration\fP to support in the
compiler. This selects between \fIIEEE1364\-1995\fP, compiler. This selects between \fIIEEE1364\-1995\fP,
\fIIEEE1364\-2001\fP, \fIIEEE1364\-2005\fP, or \fIIEEE1800-2009\fP. \fIIEEE1364\-2001\fP, \fIIEEE1364\-2005\fP, or \fIIEEE1800-2009\fP.
Normally, Icarus Verilog defaults to the latest known generation of the Normally, Icarus Verilog defaults to the latest known generation of the
language. This flag is most useful to restrict the language to a set language. This flag is most useful to restrict the language to a set
supported by tools of specific generations, for compatibility with supported by tools of specific generations, for compatibility with

View File

@ -169,8 +169,8 @@ typedef struct t_command_file {
p_command_file cmd_file_head = NULL; /* The FIFO head */ p_command_file cmd_file_head = NULL; /* The FIFO head */
p_command_file cmd_file_tail = NULL; /* The FIFO tail */ p_command_file cmd_file_tail = NULL; /* The FIFO tail */
/* Temprarily store parameter definition from command line and /* Temporarily store parameter definition from command line and
* parse it after we have delt with command file * parse it after we have dealt with command file
*/ */
static const char** defparm_base = 0; static const char** defparm_base = 0;
static int defparm_size = 0; static int defparm_size = 0;
@ -777,10 +777,10 @@ int main(int argc, char **argv)
turning the last two \ characters to null. Then we append turning the last two \ characters to null. Then we append
the lib\ivl$(suffix) to finish. */ the lib\ivl$(suffix) to finish. */
{ char *s; { char *s;
char basepath[4096], tmp[4096]; char basepath[4096], tmppath[4096];
GetModuleFileName(NULL, tmp, sizeof tmp); GetModuleFileName(NULL, tmppath, sizeof tmppath);
/* Convert to a short name to remove any embedded spaces. */ /* Convert to a short name to remove any embedded spaces. */
GetShortPathName(tmp, basepath, sizeof basepath); GetShortPathName(tmppath, basepath, sizeof basepath);
strncpy(ivl_root, basepath, MAXSIZE); strncpy(ivl_root, basepath, MAXSIZE);
ivl_root[MAXSIZE-1] = 0; ivl_root[MAXSIZE-1] = 0;
s = strrchr(ivl_root, sep); s = strrchr(ivl_root, sep);
@ -1105,7 +1105,7 @@ int main(int argc, char **argv)
/* If we are planning on opening a dependencies file, then /* If we are planning on opening a dependencies file, then
open and truncate it here. The other phases of compilation open and truncate it here. The other phases of compilation
will append to the file, so this is necessray to make sure will append to the file, so this is necessary to make sure
it starts out empty. */ it starts out empty. */
if (depfile) { if (depfile) {
FILE*fd = fopen(depfile, "w"); FILE*fd = fopen(depfile, "w");

View File

@ -729,7 +729,7 @@ NetExpr* PEBinary::elaborate_expr_base_rshift_(Design*des,
return tmp; return tmp;
} }
// Falback, handle the general case. // Fallback, handle the general case.
if (expr_wid > 0) if (expr_wid > 0)
lp = pad_to_width(lp, expr_wid, *this); lp = pad_to_width(lp, expr_wid, *this);
tmp = new NetEBShift(op_, lp, rp); tmp = new NetEBShift(op_, lp, rp);
@ -1011,7 +1011,7 @@ unsigned PEBLeftWidth::test_width(Design*des, NetScope*scope,
&& wid_left > 0 && wid_left > 0
&& wid_left < integer_width) { && wid_left < integer_width) {
wid_left = integer_width; wid_left = integer_width;
if (debug_elaborate) if (debug_elaborate)
cerr << get_fileline() << ": debug: " cerr << get_fileline() << ": debug: "
<< "Test width of unsized " << human_readable_op(op_) << "Test width of unsized " << human_readable_op(op_)
@ -1273,7 +1273,7 @@ NetExpr*PECallFunction::cast_to_width_(NetExpr*expr, int wid, bool signed_flag)
if (wid < 0) if (wid < 0)
wid = expr->expr_width(); wid = expr->expr_width();
if (debug_elaborate) if (debug_elaborate)
cerr << get_fileline() << ": debug: cast to " << wid cerr << get_fileline() << ": debug: cast to " << wid
<< " bits" << endl; << " bits" << endl;
@ -2494,11 +2494,7 @@ NetExpr* PEIdent::elaborate_expr_param_idx_up_(Design*des, NetScope*scope,
return result_ex; return result_ex;
} }
if (par_msv >= par_lsv) { base = normalize_variable_base(base, par_msv, par_lsv, wid, true);
if (par_lsv != 0) base = make_add_expr(base, -par_lsv);
} else {
base = make_sub_expr(par_lsv-wid+1, base);
}
NetExpr*tmp = par->dup_expr(); NetExpr*tmp = par->dup_expr();
tmp = new NetESelect(tmp, base, wid); tmp = new NetESelect(tmp, base, wid);
@ -2578,13 +2574,7 @@ NetExpr* PEIdent::elaborate_expr_param_idx_do_(Design*des, NetScope*scope,
return result_ex; return result_ex;
} }
if (par_msv >= par_lsv) { base = normalize_variable_base(base, par_msv, par_lsv, wid, false);
if (long offset = par_lsv+wid-1) {
base = make_add_expr(base, -offset);
}
} else {
base = make_sub_expr(par_lsv, base);
}
NetExpr*tmp = par->dup_expr(); NetExpr*tmp = par->dup_expr();
tmp = new NetESelect(tmp, base, wid); tmp = new NetESelect(tmp, base, wid);
@ -2610,7 +2600,7 @@ NetExpr* PEIdent::elaborate_expr_param_(Design*des,
if (!name_tail.index.empty()) if (!name_tail.index.empty())
use_sel = name_tail.index.back().sel; use_sel = name_tail.index.back().sel;
if (par->expr_type() == IVL_VT_REAL && if (par->expr_type() == IVL_VT_REAL &&
use_sel != index_component_t::SEL_NONE) { use_sel != index_component_t::SEL_NONE) {
perm_string name = peek_tail_name(path_); perm_string name = peek_tail_name(path_);
cerr << get_fileline() << ": error: " cerr << get_fileline() << ": error: "
@ -2742,17 +2732,10 @@ NetExpr* PEIdent::elaborate_expr_param_(Design*des,
} else { } else {
if (par_me) { if (par_me) {
long par_mv = par_me->value().as_long(); mtmp = normalize_variable_base(mtmp,
long par_lv = par_le->value().as_long(); par_me->value().as_long(),
if (par_mv >= par_lv) { par_le->value().as_long(),
mtmp = par_lv 1, true);
? make_add_expr(mtmp, 0-par_lv)
: mtmp;
} else {
if (par_lv != 0)
mtmp = make_add_expr(mtmp, 0-par_mv);
mtmp = make_sub_expr(par_lv-par_mv, mtmp);
}
} }
/* The value is constant, but the bit select /* The value is constant, but the bit select
@ -2869,7 +2852,8 @@ NetExpr* PEIdent::elaborate_expr_net_word_(Design*des, NetScope*scope,
// expression to calculate the canonical address. // expression to calculate the canonical address.
if (long base = net->array_first()) { if (long base = net->array_first()) {
word_index = make_add_expr(word_index, 0-base); word_index = normalize_variable_array_base(
word_index, base, net->array_count());
eval_expr(word_index); eval_expr(word_index);
} }
} }
@ -2945,7 +2929,7 @@ NetExpr* PEIdent::elaborate_expr_net_part_(Design*des, NetScope*scope,
cerr << get_fileline() << ": : " cerr << get_fileline() << ": : "
"Replacing select with a constant 'bx." << endl; "Replacing select with a constant 'bx." << endl;
} }
NetEConst*tmp = new NetEConst(verinum(verinum::Vx, 1, false)); NetEConst*tmp = new NetEConst(verinum(verinum::Vx, 1, false));
tmp->set_line(*this); tmp->set_line(*this);
return tmp; return tmp;
@ -3053,7 +3037,7 @@ NetExpr* PEIdent::elaborate_expr_net_idx_up_(Design*des, NetScope*scope,
} }
// Otherwise, make a part select that covers the right // Otherwise, make a part select that covers the right
// range. // range.
ex = new NetEConst(verinum(net->sig()->sb_to_idx(lsv) + ex = new NetEConst(verinum(net->sig()->sb_to_idx(lsv) +
offset)); offset));
if (warn_ob_select) { if (warn_ob_select) {
long rel_base = net->sig()->sb_to_idx(lsv) + offset; long rel_base = net->sig()->sb_to_idx(lsv) + offset;
@ -3092,12 +3076,7 @@ NetExpr* PEIdent::elaborate_expr_net_idx_up_(Design*des, NetScope*scope,
return ss; return ss;
} }
if (net->msi() > net->lsi()) { base = normalize_variable_base(base, net->msi(), net->lsi(), wid, true);
if (long offset = net->lsi())
base = make_add_expr(base, -offset);
} else {
base = make_sub_expr(net->lsi()-wid+1, base);
}
NetESelect*ss = new NetESelect(net, base, wid); NetESelect*ss = new NetESelect(net, base, wid);
ss->set_line(*this); ss->set_line(*this);
@ -3184,12 +3163,7 @@ NetExpr* PEIdent::elaborate_expr_net_idx_do_(Design*des, NetScope*scope,
return ss; return ss;
} }
if (net->msi() > net->lsi()) { base = normalize_variable_base(base, net->msi(), net->lsi(), wid, false);
if (long offset = net->lsi()+wid-1)
base = make_add_expr(base, -offset);
} else {
base = make_sub_expr(net->lsi(), base);
}
NetESelect*ss = new NetESelect(net, base, wid); NetESelect*ss = new NetESelect(net, base, wid);
ss->set_line(*this); ss->set_line(*this);
@ -3294,12 +3268,8 @@ NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope,
// complicated task because we need to generate // complicated task because we need to generate
// expressions to convert calculated bit select // expressions to convert calculated bit select
// values to canonical values that are used internally. // values to canonical values that are used internally.
ex = normalize_variable_base(ex, net->sig()->msb(), net->sig()->lsb(),
if (net->sig()->msb() < net->sig()->lsb()) { 1, true);
ex = make_sub_expr(net->sig()->lsb(), ex);
} else {
ex = make_add_expr(ex, - net->sig()->lsb());
}
NetESelect*ss = new NetESelect(net, ex, 1); NetESelect*ss = new NetESelect(net, ex, 1);
ss->set_line(*this); ss->set_line(*this);
@ -3537,7 +3507,7 @@ NetExpr*PETernary::elaborate_expr(Design*des, NetScope*scope,
// evaluation of ternary expressions, but it doesn't disallow // evaluation of ternary expressions, but it doesn't disallow
// it. The disadvantage of doing this is that semantic errors // it. The disadvantage of doing this is that semantic errors
// in the unused clause will be missed, but people don't seem // in the unused clause will be missed, but people don't seem
// to mind, and do apreciate the optimization available here. // to mind, and do appreciate the optimization available here.
if (NetEConst*tmp = dynamic_cast<NetEConst*> (con)) { if (NetEConst*tmp = dynamic_cast<NetEConst*> (con)) {
verinum cval = tmp->value(); verinum cval = tmp->value();
ivl_assert(*this, cval.len()==1); ivl_assert(*this, cval.len()==1);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2000-2009 Stephen Williams (steve@icarus.com) * Copyright (c) 2000-2010 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -198,7 +198,7 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
if (reg->array_dimensions() > 0) if (reg->array_dimensions() > 0)
return elaborate_lval_net_word_(des, scope, reg); return elaborate_lval_net_word_(des, scope, reg);
// This must be after the array word elaboration above! // This must be after the array word elaboration above!
if (reg->get_scalar() && if (reg->get_scalar() &&
use_sel != index_component_t::SEL_NONE) { use_sel != index_component_t::SEL_NONE) {
cerr << get_fileline() << ": error: can not select part of "; cerr << get_fileline() << ": error: can not select part of ";
@ -269,7 +269,8 @@ NetAssign_* PEIdent::elaborate_lval_net_word_(Design*des,
// expression to calculate the canonical address. // expression to calculate the canonical address.
if (long base = reg->array_first()) { if (long base = reg->array_first()) {
word = make_add_expr(word, 0-base); word = normalize_variable_array_base(word, base,
reg->array_count());
eval_expr(word); eval_expr(word);
} }
@ -342,7 +343,6 @@ bool PEIdent::elaborate_lval_net_bit_(Design*des,
index_tail.msb->test_width(des, scope, integer_width, integer_width, index_tail.msb->test_width(des, scope, integer_width, integer_width,
expr_type_tmp, unsized_flag_tmp); expr_type_tmp, unsized_flag_tmp);
// Bit selects have a single select expression. Evaluate the // Bit selects have a single select expression. Evaluate the
// constant value and treat it as a part select with a bit // constant value and treat it as a part select with a bit
// width of 1. // width of 1.
@ -357,10 +357,7 @@ bool PEIdent::elaborate_lval_net_bit_(Design*des,
if (mux) { if (mux) {
// Non-constant bit mux. Correct the mux for the range // Non-constant bit mux. Correct the mux for the range
// of the vector, then set the l-value part select expression. // of the vector, then set the l-value part select expression.
if (reg->msb() < reg->lsb()) mux = normalize_variable_base(mux, reg->msb(), reg->lsb(), 1, true);
mux = make_sub_expr(reg->lsb(), mux);
else if (reg->lsb() != 0)
mux = make_add_expr(mux, - reg->lsb());
lv->set_part(mux, 1); lv->set_part(mux, 1);
@ -535,20 +532,12 @@ bool PEIdent::elaborate_lval_net_idx_(Design*des,
} else { } else {
/* Correct the mux for the range of the vector. */ /* Correct the mux for the range of the vector. */
if (use_sel == index_component_t::SEL_IDX_UP) { if (use_sel == index_component_t::SEL_IDX_UP) {
if (reg->msb() > reg->lsb()) { base = normalize_variable_base(base, reg->msb(), reg->lsb(),
if (long offset = reg->lsb()) wid, true);
base = make_add_expr(base, -offset);
} else {
base = make_sub_expr(reg->lsb()-wid+1, base);
}
} else { } else {
// This is assumed to be a SEL_IDX_DO. // This is assumed to be a SEL_IDX_DO.
if (reg->msb() > reg->lsb()) { base = normalize_variable_base(base, reg->msb(), reg->lsb(),
if (long offset = reg->lsb()+wid-1) wid, false);
base = make_add_expr(base, -offset);
} else {
base = make_sub_expr(reg->lsb(), base);
}
} }
} }

View File

@ -497,7 +497,7 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
/* The array has a part/bit select at the end. */ /* The array has a part/bit select at the end. */
if (name_tail.index.size() > sig->array_dimensions()) { if (name_tail.index.size() > sig->array_dimensions()) {
if (sig->get_scalar()) { if (sig->get_scalar()) {
cerr << get_fileline() << ": error: " cerr << get_fileline() << ": error: "
<< "can not select part of "; << "can not select part of ";
if (sig->data_type() == IVL_VT_REAL) cerr << "real"; if (sig->data_type() == IVL_VT_REAL) cerr << "real";
else cerr << "scalar"; else cerr << "scalar";
@ -512,7 +512,7 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
return 0; return 0;
if (lidx_tmp < 0) { if (lidx_tmp < 0) {
cerr << get_fileline() << ": sorry: part selects " cerr << get_fileline() << ": sorry: part selects "
"straddling the start of signal (" << path_ "straddling the start of signal (" << path_
<< ") are not currently supported." << endl; << ") are not currently supported." << endl;
des->errors += 1; des->errors += 1;
@ -523,7 +523,7 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
} }
} else if (!name_tail.index.empty()) { } else if (!name_tail.index.empty()) {
if (sig->get_scalar()) { if (sig->get_scalar()) {
cerr << get_fileline() << ": error: " cerr << get_fileline() << ": error: "
<< "can not select part of "; << "can not select part of ";
if (sig->data_type() == IVL_VT_REAL) cerr << "real: "; if (sig->data_type() == IVL_VT_REAL) cerr << "real: ";
else cerr << "scalar: "; else cerr << "scalar: ";
@ -537,7 +537,7 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
return 0; return 0;
if (lidx_tmp < 0) { if (lidx_tmp < 0) {
cerr << get_fileline() << ": sorry: part selects " cerr << get_fileline() << ": sorry: part selects "
"straddling the start of signal (" << path_ "straddling the start of signal (" << path_
<< ") are not currently supported." << endl; << ") are not currently supported." << endl;
des->errors += 1; des->errors += 1;

View File

@ -1422,7 +1422,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
des->errors += 1; des->errors += 1;
continue; continue;
} }
// We do not support real inout ports at all. // We do not support real inout ports at all.
if (!prts.empty() && (prts[0]->data_type() == IVL_VT_REAL )) { if (!prts.empty() && (prts[0]->data_type() == IVL_VT_REAL )) {
cerr << pins[idx]->get_fileline() << ": error: " cerr << pins[idx]->get_fileline() << ": error: "

View File

@ -858,7 +858,7 @@ NetExpr* NetEBDiv::eval_tree(int prune_to_width)
eval_expr(right_); eval_expr(right_);
if (expr_type() == IVL_VT_REAL) return eval_tree_real_(); if (expr_type() == IVL_VT_REAL) return eval_tree_real_();
assert(expr_type() == IVL_VT_LOGIC); assert(expr_type() == IVL_VT_LOGIC);
NetEConst*lc = dynamic_cast<NetEConst*>(left_); NetEConst*lc = dynamic_cast<NetEConst*>(left_);
@ -1228,6 +1228,12 @@ NetExpr* NetEParam::eval_tree(int prune_to_width)
<< *this << endl; << *this << endl;
} }
if (solving()) {
cerr << get_fileline() << ": warning: Recursive parameter "
"reference found involving " << *this << "." << endl;
return 0;
}
assert(scope_); assert(scope_);
perm_string name = (*reference_).first; perm_string name = (*reference_).first;
const NetExpr*expr = (*reference_).second.expr; const NetExpr*expr = (*reference_).second.expr;
@ -1239,35 +1245,35 @@ NetExpr* NetEParam::eval_tree(int prune_to_width)
<< *this << " cannot be evaluated." << endl; << *this << " cannot be evaluated." << endl;
return 0; return 0;
} }
// ivl_assert(*this, expr);
NetExpr*nexpr = expr->dup_expr();
assert(nexpr);
// If the parameter that I refer to is already evaluated, then // If the parameter that I refer to is already evaluated, then
// return the constant value. // return the constant value.
if (NetEConst*tmp = dynamic_cast<NetEConst*>(nexpr)) { if (const NetEConst*tmp = dynamic_cast<const NetEConst*>(expr)) {
verinum val = tmp->value(); verinum val = tmp->value();
NetEConstParam*ptmp = new NetEConstParam(scope_, name, val); NetEConstParam*ptmp = new NetEConstParam(scope_, name, val);
ptmp->set_line(*this); ptmp->set_line(*this);
delete nexpr;
return ptmp; return ptmp;
} }
if (NetECReal*tmp = dynamic_cast<NetECReal*>(nexpr)) { if (const NetECReal*tmp = dynamic_cast<const NetECReal*>(expr)) {
verireal val = tmp->value(); verireal val = tmp->value();
NetECRealParam*ptmp = new NetECRealParam(scope_, name, val); NetECRealParam*ptmp = new NetECRealParam(scope_, name, val);
ptmp->set_line(*this); ptmp->set_line(*this);
delete nexpr;
return ptmp; return ptmp;
} }
// Try to evaluate the expression. If I cannot, then the // Try to evaluate the expression. If I cannot, then the
// expression is not a constant expression and I fail here. // expression is not a constant expression and I fail here.
solving(true);
NetExpr*nexpr = expr->dup_expr();
assert(nexpr);
NetExpr*res = nexpr->eval_tree(); NetExpr*res = nexpr->eval_tree();
solving(false);
if (res == 0) { if (res == 0) {
cerr << get_fileline() << ": internal error: Unable to evaluate " cerr << get_fileline() << ": internal error: Unable to evaluate ";
<< "parameter " << name << " expression: " if (expr_type() == IVL_VT_REAL) cerr << "real ";
cerr << "parameter " << name << " expression: "
<< *nexpr << endl; << *nexpr << endl;
delete nexpr; delete nexpr;
return 0; return 0;

View File

@ -162,11 +162,11 @@ end
endmodule endmodule
module des(pt, key, ct, clk); module des(pt, key, ct, clk);
input [1:64] pt; input [1:64] pt;
input [1:64] key; input [1:64] key;
output [1:64] ct; output [1:64] ct;
input clk; input clk;
wire [1:48] k1x,k2x,k3x,k4x,k5x,k6x,k7x,k8x,k9x,k10x,k11x,k12x,k13x,k14x,k15x,k16x; wire [1:48] k1x,k2x,k3x,k4x,k5x,k6x,k7x,k8x,k9x,k10x,k11x,k12x,k13x,k14x,k15x,k16x;
wire [1:32] l0x,l1x,l2x,l3x,l4x,l5x,l6x,l7x,l8x,l9x,l10x,l11x,l12x,l13x,l14x,l15x,l16x; wire [1:32] l0x,l1x,l2x,l3x,l4x,l5x,l6x,l7x,l8x,l9x,l10x,l11x,l12x,l13x,l14x,l15x,l16x;
wire [1:32] r0x,r1x,r2x,r3x,r4x,r5x,r6x,r7x,r8x,r9x,r10x,r11x,r12x,r13x,r14x,r15x,r16x; wire [1:32] r0x,r1x,r2x,r3x,r4x,r5x,r6x,r7x,r8x,r9x,r10x,r11x,r12x,r13x,r14x,r15x,r16x;
@ -194,9 +194,9 @@ endmodule
module pc1(key, c0x, d0x); module pc1(key, c0x, d0x);
input [1:64] key; input [1:64] key;
output [1:28] c0x, d0x; output [1:28] c0x, d0x;
wire [1:56] XX; wire [1:56] XX;
assign XX[1]=key[57]; assign XX[2]=key[49]; assign XX[3]=key[41]; assign XX[4]=key[33]; assign XX[5]=key[25]; assign XX[6]=key[17]; assign XX[7]=key[9]; assign XX[1]=key[57]; assign XX[2]=key[49]; assign XX[3]=key[41]; assign XX[4]=key[33]; assign XX[5]=key[25]; assign XX[6]=key[17]; assign XX[7]=key[9];
assign XX[8]=key[1]; assign XX[9]=key[58]; assign XX[10]=key[50]; assign XX[11]=key[42]; assign XX[12]=key[34]; assign XX[13]=key[26]; assign XX[14]=key[18]; assign XX[8]=key[1]; assign XX[9]=key[58]; assign XX[10]=key[50]; assign XX[11]=key[42]; assign XX[12]=key[34]; assign XX[13]=key[26]; assign XX[14]=key[18];
@ -213,9 +213,9 @@ endmodule
module pc2(c,d,k); module pc2(c,d,k);
input [1:28] c,d; input [1:28] c,d;
output [1:48] k; output [1:48] k;
wire [1:56] YY; wire [1:56] YY;
assign YY[1:28]=c; assign YY[29:56]=d; assign YY[1:28]=c; assign YY[29:56]=d;
@ -231,7 +231,7 @@ endmodule
module rol1(o, i); module rol1(o, i);
output [1:28] o; output [1:28] o;
input [1:28] i; input [1:28] i;
assign o={i[2:28],i[1]}; assign o={i[2:28],i[1]};
@ -240,7 +240,7 @@ endmodule
module rol2(o, i); module rol2(o, i);
output [1:28] o; output [1:28] o;
input [1:28] i; input [1:28] i;
assign o={i[3:28],i[1:2]}; assign o={i[3:28],i[1:2]};
@ -248,10 +248,10 @@ endmodule
module keysched(key,k1x,k2x,k3x,k4x,k5x,k6x,k7x,k8x,k9x,k10x,k11x,k12x,k13x,k14x,k15x,k16x); module keysched(key,k1x,k2x,k3x,k4x,k5x,k6x,k7x,k8x,k9x,k10x,k11x,k12x,k13x,k14x,k15x,k16x);
input [1:64] key; input [1:64] key;
output [1:48] k1x,k2x,k3x,k4x,k5x,k6x,k7x,k8x,k9x,k10x,k11x,k12x,k13x,k14x,k15x,k16x; output [1:48] k1x,k2x,k3x,k4x,k5x,k6x,k7x,k8x,k9x,k10x,k11x,k12x,k13x,k14x,k15x,k16x;
wire [1:28] c0x,c1x,c2x,c3x,c4x,c5x,c6x,c7x,c8x,c9x,c10x,c11x,c12x,c13x,c14x,c15x,c16x; wire [1:28] c0x,c1x,c2x,c3x,c4x,c5x,c6x,c7x,c8x,c9x,c10x,c11x,c12x,c13x,c14x,c15x,c16x;
wire [1:28] d0x,d1x,d2x,d3x,d4x,d5x,d6x,d7x,d8x,d9x,d10x,d11x,d12x,d13x,d14x,d15x,d16x; wire [1:28] d0x,d1x,d2x,d3x,d4x,d5x,d6x,d7x,d8x,d9x,d10x,d11x,d12x,d13x,d14x,d15x,d16x;
pc1 pc1(key, c0x, d0x); pc1 pc1(key, c0x, d0x);
@ -294,10 +294,10 @@ endmodule
module s1(clk, b, so); module s1(clk, b, so);
input clk; input clk;
input [1:6] b; input [1:6] b;
output [1:4] so; output [1:4] so;
reg [1:4] so; reg [1:4] so;
always @(posedge clk) always @(posedge clk)
casex(b) casex(b)
@ -370,10 +370,10 @@ endmodule
module s2(clk, b, so); module s2(clk, b, so);
input clk; input clk;
input [1:6] b; input [1:6] b;
output [1:4] so; output [1:4] so;
reg [1:4] so; reg [1:4] so;
always @(posedge clk) always @(posedge clk)
casex(b) casex(b)
@ -446,10 +446,10 @@ endmodule
module s3(clk, b, so); module s3(clk, b, so);
input clk; input clk;
input [1:6] b; input [1:6] b;
output [1:4] so; output [1:4] so;
reg [1:4] so; reg [1:4] so;
always @(posedge clk) always @(posedge clk)
casex(b) casex(b)
@ -522,10 +522,10 @@ endmodule
module s4(clk, b, so); module s4(clk, b, so);
input clk; input clk;
input [1:6] b; input [1:6] b;
output [1:4] so; output [1:4] so;
reg [1:4] so; reg [1:4] so;
always @(posedge clk) always @(posedge clk)
casex(b) casex(b)
@ -598,10 +598,10 @@ endmodule
module s5(clk, b, so); module s5(clk, b, so);
input clk; input clk;
input [1:6] b; input [1:6] b;
output [1:4] so; output [1:4] so;
reg [1:4] so; reg [1:4] so;
always @(posedge clk) always @(posedge clk)
casex(b) casex(b)
@ -674,10 +674,10 @@ endmodule
module s6(clk, b, so); module s6(clk, b, so);
input clk; input clk;
input [1:6] b; input [1:6] b;
output [1:4] so; output [1:4] so;
reg [1:4] so; reg [1:4] so;
always @(posedge clk) always @(posedge clk)
casex(b) casex(b)
@ -750,10 +750,10 @@ endmodule
module s7(clk, b, so); module s7(clk, b, so);
input clk; input clk;
input [1:6] b; input [1:6] b;
output [1:4] so; output [1:4] so;
reg [1:4] so; reg [1:4] so;
always @(posedge clk) always @(posedge clk)
casex(b) casex(b)
@ -826,10 +826,10 @@ endmodule
module s8(clk, b, so); module s8(clk, b, so);
input clk; input clk;
input [1:6] b; input [1:6] b;
output [1:4] so; output [1:4] so;
reg [1:4] so; reg [1:4] so;
always @(posedge clk) always @(posedge clk)
casex(b) casex(b)
@ -902,8 +902,8 @@ endmodule
module ip(pt, l0x, r0x); module ip(pt, l0x, r0x);
input [1:64] pt; input [1:64] pt;
output [1:32] l0x, r0x; output [1:32] l0x, r0x;
assign l0x[1]=pt[58]; assign l0x[2]=pt[50]; assign l0x[3]=pt[42]; assign l0x[4]=pt[34]; assign l0x[1]=pt[58]; assign l0x[2]=pt[50]; assign l0x[3]=pt[42]; assign l0x[4]=pt[34];
assign l0x[5]=pt[26]; assign l0x[6]=pt[18]; assign l0x[7]=pt[10]; assign l0x[8]=pt[2]; assign l0x[5]=pt[26]; assign l0x[6]=pt[18]; assign l0x[7]=pt[10]; assign l0x[8]=pt[2];
@ -941,10 +941,10 @@ endmodule
module desxor1(e,b1x,b2x,b3x,b4x,b5x,b6x,b7x,b8x,k); module desxor1(e,b1x,b2x,b3x,b4x,b5x,b6x,b7x,b8x,k);
input [1:48] e; input [1:48] e;
output [1:6] b1x,b2x,b3x,b4x,b5x,b6x,b7x,b8x; output [1:6] b1x,b2x,b3x,b4x,b5x,b6x,b7x,b8x;
input [1:48] k; input [1:48] k;
wire [1:48] XX; wire [1:48] XX;
assign XX = k ^ e; assign XX = k ^ e;
assign b1x = XX[1:6]; assign b1x = XX[1:6];
@ -960,9 +960,9 @@ endmodule
module pp(so1x,so2x,so3x,so4x,so5x,so6x,so7x,so8x,ppo); module pp(so1x,so2x,so3x,so4x,so5x,so6x,so7x,so8x,ppo);
input [1:4] so1x,so2x,so3x,so4x,so5x,so6x,so7x,so8x; input [1:4] so1x,so2x,so3x,so4x,so5x,so6x,so7x,so8x;
output [1:32] ppo; output [1:32] ppo;
wire [1:32] XX; wire [1:32] XX;
assign XX[1:4]=so1x; assign XX[5:8]=so2x; assign XX[9:12]=so3x; assign XX[13:16]=so4x; assign XX[1:4]=so1x; assign XX[5:8]=so2x; assign XX[9:12]=so3x; assign XX[13:16]=so4x;
assign XX[17:20]=so5x; assign XX[21:24]=so6x; assign XX[25:28]=so7x; assign XX[29:32]=so8x; assign XX[17:20]=so5x; assign XX[21:24]=so6x; assign XX[25:28]=so7x; assign XX[29:32]=so8x;
@ -980,8 +980,8 @@ endmodule
module desxor2(d,l,q); module desxor2(d,l,q);
input [1:32] d,l; input [1:32] d,l;
output [1:32] q; output [1:32] q;
assign q = d ^ l; assign q = d ^ l;
@ -994,10 +994,10 @@ input [1:32] li, ri;
input [1:48] k; input [1:48] k;
output [1:32] lo, ro; output [1:32] lo, ro;
wire [1:48] e; wire [1:48] e;
wire [1:6] b1x,b2x,b3x,b4x,b5x,b6x,b7x,b8x; wire [1:6] b1x,b2x,b3x,b4x,b5x,b6x,b7x,b8x;
wire [1:4] so1x,so2x,so3x,so4x,so5x,so6x,so7x,so8x; wire [1:4] so1x,so2x,so3x,so4x,so5x,so6x,so7x,so8x;
wire [1:32] ppo; wire [1:32] ppo;
xp xp(ri, e); xp xp(ri, e);
desxor1 desxor1(e, b1x, b2x, b3x, b4x, b5x, b6x, b7x, b8x, k); desxor1 desxor1(e, b1x, b2x, b3x, b4x, b5x, b6x, b7x, b8x, k);
@ -1018,7 +1018,7 @@ endmodule
module fp(l,r,ct); module fp(l,r,ct);
input [1:32] l,r; input [1:32] l,r;
output [1:64] ct; output [1:64] ct;
assign ct[1]=r[8]; assign ct[2]=l[8]; assign ct[3]=r[16]; assign ct[4]=l[16]; assign ct[5]=r[24]; assign ct[6]=l[24]; assign ct[7]=r[32]; assign ct[8]=l[32]; assign ct[1]=r[8]; assign ct[2]=l[8]; assign ct[3]=r[16]; assign ct[4]=l[16]; assign ct[5]=r[24]; assign ct[6]=l[24]; assign ct[7]=r[32]; assign ct[8]=l[32];

View File

@ -55,12 +55,12 @@
module register (out, val, clk, oe); module register (out, val, clk, oe);
output [7:0] out; output [7:0] out;
input [7:0] val; input [7:0] val;
input clk, oe; input clk, oe;
reg [7:0] Q; reg [7:0] Q;
wire [7:0] out; wire [7:0] out;
bufif0 drv[7:0](out, Q, oe); bufif0 drv[7:0](out, Q, oe);

View File

@ -252,7 +252,7 @@ endmodule // sqrt32
module main; module main;
reg [31:0] x; reg [31:0] x;
reg clk, reset; reg clk, reset;
wire [15:0] y; wire [15:0] y;
wire rdy; wire rdy;
@ -354,7 +354,7 @@ module chip_root(clk, rdy, reset, x, y);
input [31:0] x; input [31:0] x;
output [15:0] y; output [15:0] y;
wire clk_int; wire clk_int;
(* cellref="BUFG:O,I" *) (* cellref="BUFG:O,I" *)
buf gbuf (clk_int, clk); buf gbuf (clk_int, clk);

View File

@ -907,7 +907,7 @@ NetNet* NetEUnary::synthesize(Design*des, NetScope*scope, NetExpr*root)
return sig; return sig;
} }
cerr << get_fileline() << ": iternal error: " cerr << get_fileline() << ": internal error: "
<< "NetEUnary::synthesize cannot handle op_=" << op_ << endl; << "NetEUnary::synthesize cannot handle op_=" << op_ << endl;
des->errors += 1; des->errors += 1;
return expr_->synthesize(des, scope, root); return expr_->synthesize(des, scope, root);
@ -1328,7 +1328,7 @@ static NetEvWait* make_func_trigger(Design*des, NetScope*scope, NetExpr*root)
delete nset; delete nset;
return trigger; return trigger;
} }
NetNet* NetESFunc::synthesize(Design*des, NetScope*scope, NetExpr*root) NetNet* NetESFunc::synthesize(Design*des, NetScope*scope, NetExpr*root)
{ {

View File

@ -607,7 +607,7 @@ extern double ivl_const_real(ivl_net_const_t net);
* *
* The discipline domain will not be IVL_DIS_NONE. The "none" domain * The discipline domain will not be IVL_DIS_NONE. The "none" domain
* is a place-holder internally for incomplete parsing, and is also * is a place-holder internally for incomplete parsing, and is also
* available for code generaters to use. * available for code generators to use.
*/ */
extern const char*ivl_discipline_name(ivl_discipline_t net); extern const char*ivl_discipline_name(ivl_discipline_t net);
extern ivl_dis_domain_t ivl_discipline_domain(ivl_discipline_t net); extern ivl_dis_domain_t ivl_discipline_domain(ivl_discipline_t net);
@ -1696,7 +1696,7 @@ extern int ivl_scope_time_units(ivl_scope_t net);
* *
* ivl_signal_discipline * ivl_signal_discipline
* If the signal has been declared with a domain (Verilog-AMS) then * If the signal has been declared with a domain (Verilog-AMS) then
* this function wil return a non-nil ivl_discipline_t. * this function will return a non-nil ivl_discipline_t.
* *
* ivl_signal_msb * ivl_signal_msb
* ivl_signal_lsb * ivl_signal_lsb

View File

@ -1394,19 +1394,19 @@ static void do_expand(int use_args)
str_buf[idx+1] = '0'; str_buf[idx+1] = '0';
str_buf[idx+2] = '4'; str_buf[idx+2] = '4';
str_buf[idx+3] = '2'; str_buf[idx+3] = '2';
idx += 4; idx += 4;
continue; continue;
} }
if (*cp == '\\') { if (*cp == '\\') {
str_buf[idx] = '\\'; str_buf[idx] = '\\';
str_buf[idx+1] = '1'; str_buf[idx+1] = '1';
str_buf[idx+2] = '3'; str_buf[idx+2] = '3';
str_buf[idx+3] = '4'; str_buf[idx+3] = '4';
idx += 4; idx += 4;
continue; continue;
} }
str_buf[idx] = *cp; str_buf[idx] = *cp;
idx += 1; idx += 1;
} }
str_buf[idx] = 0; str_buf[idx] = 0;
idx += 1; idx += 1;

View File

@ -1179,7 +1179,7 @@ static void process_ucdrive(const char*txt)
cp += strspn(cp, " \t"); cp += strspn(cp, " \t");
if (strncmp(cp, "//", 2) != 0 && if (strncmp(cp, "//", 2) != 0 &&
(size_t)(cp-yytext) != strlen(yytext)) { (size_t)(cp-yytext) != strlen(yytext)) {
VLerror(yylloc, "Invalid `unconnected_dirve directive (extra " VLerror(yylloc, "Invalid `unconnected_drive directive (extra "
"garbage after precision)."); "garbage after precision).");
return; return;
} }

View File

@ -872,7 +872,7 @@ int main(int argc, char*argv[])
if (gn_cadence_types_flag) if (gn_cadence_types_flag)
lexor_keyword_mask |= GN_KEYWORDS_ICARUS; lexor_keyword_mask |= GN_KEYWORDS_ICARUS;
if (gn_verilog_ams_flag) if (gn_verilog_ams_flag)
lexor_keyword_mask |= GN_KEYWORDS_VAMS_2_3; lexor_keyword_mask |= GN_KEYWORDS_VAMS_2_3;

View File

@ -84,7 +84,7 @@ Download the msys-1.x.x.exe and msysdtc-1.x.x.exe binaries. These are
self-installing packages. Install msys first, and then msysDTC. Most self-installing packages. Install msys first, and then msysDTC. Most
likely, you want to install them in c:/msys. (The msysDTK is installed likely, you want to install them in c:/msys. (The msysDTK is installed
in the same location, as it is an add-on.) in the same location, as it is an add-on.)
This install should be easy and reliable. This install should be easy and reliable.
The installation will leave an "msys" icon on your desktop and in the The installation will leave an "msys" icon on your desktop and in the

View File

@ -341,8 +341,7 @@ void NetScope::evaluate_parameter_logic_(Design*des, param_ref_t cur)
eval_expr((*cur).second.msb); eval_expr((*cur).second.msb);
if (! eval_as_long(msb, (*cur).second.msb)) { if (! eval_as_long(msb, (*cur).second.msb)) {
cerr << (*cur).second.expr->get_fileline() cerr << (*cur).second.expr->get_fileline()
<< ": internal error: " << ": error: Unable to evaluate msb expression "
<< "unable to evaluate msb expression "
<< "for parameter " << (*cur).first << ": " << "for parameter " << (*cur).first << ": "
<< *(*cur).second.msb << endl; << *(*cur).second.msb << endl;
des->errors += 1; des->errors += 1;
@ -357,8 +356,7 @@ void NetScope::evaluate_parameter_logic_(Design*des, param_ref_t cur)
eval_expr((*cur).second.lsb); eval_expr((*cur).second.lsb);
if (! eval_as_long(lsb, (*cur).second.lsb)) { if (! eval_as_long(lsb, (*cur).second.lsb)) {
cerr << (*cur).second.expr->get_fileline() cerr << (*cur).second.expr->get_fileline()
<< ": internal error: " << ": error: Unable to evaluate lsb expression "
<< "unable to evaluate lsb expression "
<< "for parameter " << (*cur).first << ": " << "for parameter " << (*cur).first << ": "
<< *(*cur).second.lsb << endl; << *(*cur).second.lsb << endl;
des->errors += 1; des->errors += 1;
@ -384,10 +382,10 @@ void NetScope::evaluate_parameter_logic_(Design*des, param_ref_t cur)
case IVL_VT_REAL: case IVL_VT_REAL:
if (! dynamic_cast<const NetECReal*>(expr)) { if (! dynamic_cast<const NetECReal*>(expr)) {
cerr << expr->get_fileline() cerr << expr->get_fileline()
<< ": internal error: " << ": error: Unable to evaluate real parameter "
<< "unable to evaluate real parameter value: " << (*cur).first << " value: " << *expr << endl;
<< *expr << endl;
des->errors += 1; des->errors += 1;
(*cur).second.expr = NULL;
return; return;
} }
break; break;
@ -396,11 +394,10 @@ void NetScope::evaluate_parameter_logic_(Design*des, param_ref_t cur)
case IVL_VT_BOOL: case IVL_VT_BOOL:
if (! dynamic_cast<const NetEConst*>(expr)) { if (! dynamic_cast<const NetEConst*>(expr)) {
cerr << expr->get_fileline() cerr << expr->get_fileline()
<< ": internal error: " << ": error: Unable to evaluate parameter "
<< "unable to evaluate parameter " << (*cur).first << " value: " << *expr << endl;
<< (*cur).first
<< " value: " << *expr << endl;
des->errors += 1; des->errors += 1;
(*cur).second.expr = NULL;
return; return;
} }
break; break;
@ -408,8 +405,9 @@ void NetScope::evaluate_parameter_logic_(Design*des, param_ref_t cur)
default: default:
cerr << expr->get_fileline() cerr << expr->get_fileline()
<< ": internal error: " << ": internal error: "
<< "unhandled expression type?" << endl; << "Unhandled expression type?" << endl;
des->errors += 1; des->errors += 1;
(*cur).second.expr = NULL;
return; return;
} }
@ -522,7 +520,13 @@ void NetScope::evaluate_parameter_real_(Design*des, param_ref_t cur)
if (NetECReal*tmp = dynamic_cast<NetECReal*>(expr)) { if (NetECReal*tmp = dynamic_cast<NetECReal*>(expr)) {
res = tmp; res = tmp;
} else { } else {
ivl_assert(*expr, 0); cerr << expr->get_fileline()
<< ": error: "
<< "Unable to evaluate real parameter "
<< (*cur).first << " value: " << *expr << endl;
des->errors += 1;
(*cur).second.expr = NULL;
return;
} }
break; break;
@ -533,12 +537,23 @@ void NetScope::evaluate_parameter_real_(Design*des, param_ref_t cur)
res = new NetECReal(val); res = new NetECReal(val);
res->set_line(*tmp); res->set_line(*tmp);
} else { } else {
ivl_assert(*expr, 0); cerr << expr->get_fileline()
<< ": error: "
<< "Unable to evaluate parameter "
<< (*cur).first << " value: " << *expr << endl;
des->errors += 1;
(*cur).second.expr = NULL;
return;
} }
break; break;
default: default:
ivl_assert(*expr, 0); cerr << expr->get_fileline()
<< ": internal error: "
<< "Unhandled expression type?" << endl;
des->errors += 1;
(*cur).second.expr = NULL;
return;
break; break;
} }
@ -586,7 +601,7 @@ void NetScope::evaluate_parameter_real_(Design*des, param_ref_t cur)
if (! from_flag) { if (! from_flag) {
cerr << res->get_fileline() << ": error: " cerr << res->get_fileline() << ": error: "
<< "Parameter value " << value << "Parameter value " << value
<< " is out of range for parameter " << (*cur).first << " is out of range for real parameter " << (*cur).first
<< "." << endl; << "." << endl;
des->errors += 1; des->errors += 1;
} }
@ -612,7 +627,7 @@ void NetScope::evaluate_parameters(Design*des)
// Resolve the expression type (signed/unsigned) if the // Resolve the expression type (signed/unsigned) if the
// expression is present. It is possible to not be // expression is present. It is possible to not be
// present if there are earlier errors en elaboration. // present if there are earlier errors in elaboration.
if (cur->second.expr) if (cur->second.expr)
cur->second.expr->resolve_pexpr_type(); cur->second.expr->resolve_pexpr_type();

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2002-2009 Stephen Williams (steve@icarus.com) * Copyright (c) 2002-2010 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -488,18 +488,21 @@ const NetScope* NetECRealParam::scope() const
NetEParam::NetEParam() NetEParam::NetEParam()
: des_(0), scope_(0) : des_(0), scope_(0)
{ {
solving_ = false;
} }
NetEParam::NetEParam(Design*d, NetScope*s, perm_string n) NetEParam::NetEParam(Design*d, NetScope*s, perm_string n)
: des_(d), scope_(s), reference_(scope_->find_parameter(n)) : des_(d), scope_(s), reference_(scope_->find_parameter(n))
{ {
cast_signed_base_(reference_->second.signed_flag); cast_signed_base_(reference_->second.signed_flag);
solving_ = false;
} }
NetEParam::NetEParam(Design*d, NetScope*s, ref_t ref) NetEParam::NetEParam(Design*d, NetScope*s, ref_t ref)
: des_(d), scope_(s), reference_(ref) : des_(d), scope_(s), reference_(ref)
{ {
cast_signed_base_(reference_->second.signed_flag); cast_signed_base_(reference_->second.signed_flag);
solving_ = false;
} }
NetEParam::~NetEParam() NetEParam::~NetEParam()
@ -519,10 +522,21 @@ ivl_variable_type_t NetEParam::expr_type() const
NetEParam* NetEParam::dup_expr() const NetEParam* NetEParam::dup_expr() const
{ {
NetEParam*tmp = new NetEParam(des_, scope_, reference_); NetEParam*tmp = new NetEParam(des_, scope_, reference_);
tmp->solving(solving_);
tmp->set_line(*this); tmp->set_line(*this);
return tmp; return tmp;
} }
void NetEParam::solving(bool arg)
{
solving_ = arg;
}
bool NetEParam::solving() const
{
return solving_;
}
NetESelect::NetESelect(NetExpr*exp, NetExpr*base, unsigned wid) NetESelect::NetESelect(NetExpr*exp, NetExpr*base, unsigned wid)
: expr_(exp), base_(base) : expr_(exp), base_(base)
{ {

View File

@ -382,7 +382,7 @@ void Nexus::unlink(Link*that)
} }
// If the link I'm removing was a driver for this nexus, then // If the link I'm removing was a driver for this nexus, then
// cancel my guess of the driven value. // cancel my guess of the driven value.
if (that->get_dir() != Link::INPUT) if (that->get_dir() != Link::INPUT)
driven_ = NO_GUESS; driven_ = NO_GUESS;

View File

@ -251,14 +251,14 @@ void NetScope::print_type(ostream&stream) const
break; break;
case FORK_JOIN: case FORK_JOIN:
stream << "parallel block"; stream << "parallel block";
break; break;
case FUNC: case FUNC:
stream << "function"; stream << "function";
break; break;
case MODULE: case MODULE:
stream << "module <" << (module_name_ ? module_name_.str() : "") stream << "module <" << (module_name_ ? module_name_.str() : "")
<< "> instance"; << "> instance";
break; break;
case TASK: case TASK:
stream << "task"; stream << "task";
break; break;

View File

@ -227,7 +227,7 @@ bool NetPins::is_linked(void)
NetObj::NetObj(NetScope*s, perm_string n, unsigned np) NetObj::NetObj(NetScope*s, perm_string n, unsigned np)
: NetPins(np), scope_(s), name_(n), delay1_(0), delay2_(0), delay3_(0) : NetPins(np), scope_(s), name_(n), delay1_(0), delay2_(0), delay3_(0)
{ {
/* Don't /* Don't
ivl_assert(*this, np > 0); ivl_assert(*this, np > 0);
* because it would happen before we get to print a useful * because it would happen before we get to print a useful
* message in the NetNet constructor * message in the NetNet constructor

View File

@ -1829,7 +1829,7 @@ class NetPartSelect : public NetNode {
* that makes sense for the technology. * that makes sense for the technology.
* *
* A NetBUFZ is transparent if strengths are passed through it without * A NetBUFZ is transparent if strengths are passed through it without
* change. A NetBUFZ is non-transparent if values other then HiZ are * change. A NetBUFZ is non-transparent if values other than HiZ are
* converted to the strength of the output. * converted to the strength of the output.
*/ */
class NetBUFZ : public NetNode { class NetBUFZ : public NetNode {
@ -3574,6 +3574,8 @@ class NetEParam : public NetExpr {
virtual ivl_variable_type_t expr_type() const; virtual ivl_variable_type_t expr_type() const;
virtual NetExpr* eval_tree(int prune_to_width = -1); virtual NetExpr* eval_tree(int prune_to_width = -1);
virtual NetEParam* dup_expr() const; virtual NetEParam* dup_expr() const;
void solving(bool arg);
bool solving() const;
virtual void dump(ostream&) const; virtual void dump(ostream&) const;
@ -3582,6 +3584,7 @@ class NetEParam : public NetExpr {
NetScope*scope_; NetScope*scope_;
typedef map<perm_string,NetScope::param_expr_t>::iterator ref_t; typedef map<perm_string,NetScope::param_expr_t>::iterator ref_t;
ref_t reference_; ref_t reference_;
bool solving_;
NetEParam(class Design*des, NetScope*scope, ref_t ref); NetEParam(class Design*des, NetScope*scope, ref_t ref);
}; };

View File

@ -161,7 +161,7 @@ NetNet* cast_to_real(Design*des, NetScope*scope, NetNet*src)
* NetEBAdd node that has the input expression and an expression made * NetEBAdd node that has the input expression and an expression made
* from the constant value. * from the constant value.
*/ */
NetExpr* make_add_expr(NetExpr*expr, long val) static NetExpr* make_add_expr(NetExpr*expr, long val)
{ {
if (val == 0) if (val == 0)
return expr; return expr;
@ -190,10 +190,14 @@ NetExpr* make_add_expr(NetExpr*expr, long val)
return res; return res;
} }
NetExpr* make_sub_expr(long val, NetExpr*expr) /*
* Subtract an existing expression from a signed constant.
*/
static NetExpr* make_sub_expr(long val, NetExpr*expr)
{ {
verinum val_v (val, expr->expr_width()); verinum val_v (val, expr->expr_width());
val_v.has_sign(true); val_v.has_sign(true);
NetEConst*val_c = new NetEConst(val_v); NetEConst*val_c = new NetEConst(val_v);
val_c->set_line(*expr); val_c->set_line(*expr);
@ -203,6 +207,150 @@ NetExpr* make_sub_expr(long val, NetExpr*expr)
return res; return res;
} }
/*
* This routine is used to calculate the number of bits needed to
* contain the given number.
*/
static unsigned num_bits(long arg)
{
unsigned res = 0;
/* For a negative value we have room for one extra value, but
* we have a signed result so we need an extra bit for this. */
if (arg < 0) {
arg = -arg - 1;
res += 1;
}
/* Calculate the number of bits needed here. */
while (arg) {
res += 1;
arg >>= 1;
}
return res;
}
/*
* This routine generates the normalization expression needed for a variable
* bit select or a variable base expression for an indexed part select.
*/
NetExpr *normalize_variable_base(NetExpr *base, long msb, long lsb,
unsigned long wid, bool is_up)
{
long offset = lsb;
if (msb < lsb) {
/* Correct the offset if needed. */
if (is_up) offset -= wid - 1;
/* Calculate the space needed for the offset. */
unsigned min_wid = num_bits(offset);
/* We need enough space for the larger of the offset or the
* base expression. */
if (min_wid < base->expr_width()) min_wid = base->expr_width();
/* Now that we have the minimum needed width increase it by
* one to make room for the normalization calculation. */
min_wid += 1;
/* Pad the base expression to the correct width. */
base = pad_to_width(base, min_wid, *base);
/* If the base expression is unsigned and either the lsb
* is negative or it does not fill the width of the base
* expression then we could generate negative normalized
* values so cast the expression to signed to get the
* math correct. */
if ((lsb < 0 || num_bits(lsb+1) <= base->expr_width()) &&
! base->has_sign()) {
/* We need this extra select to hide the signed
* property from the padding above. It will be
* removed automatically during code generation. */
NetESelect *tmp = new NetESelect(base, 0 , min_wid);
tmp->set_line(*base);
tmp->cast_signed(true);
base = tmp;
}
/* Normalize the expression. */
base = make_sub_expr(offset, base);
} else {
/* Correct the offset if needed. */
if (!is_up) offset += wid - 1;
/* If the offset is zero then just return the base (index)
* expression. */
if (offset == 0) return base;
/* Calculate the space needed for the offset. */
unsigned min_wid = num_bits(-offset);
/* We need enough space for the larger of the offset or the
* base expression. */
if (min_wid < base->expr_width()) min_wid = base->expr_width();
/* Now that we have the minimum needed width increase it by
* one to make room for the normalization calculation. */
min_wid += 1;
/* Pad the base expression to the correct width. */
base = pad_to_width(base, min_wid, *base);
/* If the offset is greater than zero then we need to do
* signed math to get the location value correct. */
if (offset > 0 && ! base->has_sign()) {
/* We need this extra select to hide the signed
* property from the padding above. It will be
* removed automatically during code generation. */
NetESelect *tmp = new NetESelect(base, 0 , min_wid);
tmp->set_line(*base);
tmp->cast_signed(true);
base = tmp;
}
/* Normalize the expression. */
base = make_add_expr(base, -offset);
}
return base;
}
/*
* This routine generates the normalization expression needed for a variable
* array word select.
*/
NetExpr *normalize_variable_array_base(NetExpr *base, long offset,
unsigned count)
{
assert(offset != 0);
/* Calculate the space needed for the offset. */
unsigned min_wid = num_bits(-offset);
/* We need enough space for the larger of the offset or the base
* expression. */
if (min_wid < base->expr_width()) min_wid = base->expr_width();
/* Now that we have the minimum needed width increase it by one
* to make room for the normalization calculation. */
min_wid += 1;
/* Pad the base expression to the correct width. */
base = pad_to_width(base, min_wid, *base);
/* If the offset is greater than zero then we need to do signed
* math to get the location value correct. */
if (offset > 0 && ! base->has_sign()) {
/* We need this extra select to hide the signed property
* from the padding above. It will be removed automatically
* during code generation. */
NetESelect *tmp = new NetESelect(base, 0 , min_wid);
tmp->set_line(*base);
tmp->cast_signed(true);
base = tmp;
}
/* Normalize the expression. */
base = make_add_expr(base, -offset);
/* We should not need to do this, but .array/port does not
* handle a small signed index correctly and it is a major
* effort to fix it. For now we will just pad the expression
* enough so that any negative value when converted to
* unsigned is larger than the maximum array word. */
if (base->has_sign()) {
unsigned range_wid = num_bits(count-1) + 1;
if (min_wid < range_wid) {
base = pad_to_width(base, range_wid, *base);
}
}
return base;
}
NetEConst* make_const_x(unsigned long wid) NetEConst* make_const_x(unsigned long wid)
{ {
verinum xxx (verinum::Vx, wid); verinum xxx (verinum::Vx, wid);
@ -289,8 +437,15 @@ NetExpr* elab_and_eval(Design*des, NetScope*scope,
void eval_expr(NetExpr*&expr, int prune_width) void eval_expr(NetExpr*&expr, int prune_width)
{ {
assert(expr); assert(expr);
if (dynamic_cast<NetEConst*>(expr)) return;
if (dynamic_cast<NetECReal*>(expr)) return; if (dynamic_cast<NetECReal*>(expr)) return;
/* Resize a constant if allowed and needed. */
if (NetEConst *tmp = dynamic_cast<NetEConst*>(expr)) {
if (prune_width <= 0) return;
if (tmp->has_width()) return;
if ((unsigned)prune_width <= tmp->expr_width()) return;
expr = pad_to_width(expr, (unsigned)prune_width, *expr);
return;
}
NetExpr*tmp = expr->eval_tree(prune_width); NetExpr*tmp = expr->eval_tree(prune_width);
if (tmp != 0) { if (tmp != 0) {
@ -423,7 +578,7 @@ const char *human_readable_op(const char op, bool unary)
case '>': type = ">"; break; case '>': type = ">"; break;
case 'L': type = "<="; break; case 'L': type = "<="; break;
case 'G': type = ">="; break; case 'G': type = ">="; break;
case '^': type = "^"; break; // XOR case '^': type = "^"; break; // XOR
case 'X': type = "~^"; break; // XNOR case 'X': type = "~^"; break; // XNOR
case '&': type = "&"; break; // Bitwise AND case '&': type = "&"; break; // Bitwise AND

View File

@ -91,6 +91,15 @@ extern NetExpr*condition_reduce(NetExpr*expr);
*/ */
extern NetNet*crop_to_width(Design*des, NetNet*n, unsigned w); extern NetNet*crop_to_width(Design*des, NetNet*n, unsigned w);
/*
* These functions generate an equation to normalize an expression using
* the provided vector/array information.
*/
extern NetExpr*normalize_variable_base(NetExpr *base, long msb, long lsb,
unsigned long wid, bool is_up);
extern NetExpr*normalize_variable_array_base(NetExpr *base, long offset,
unsigned count);
/* /*
* This function takes as input a NetNet signal and adds a constant * This function takes as input a NetNet signal and adds a constant
* value to it. If the val is 0, then simply return sig. Otherwise, * value to it. If the val is 0, then simply return sig. Otherwise,
@ -99,23 +108,6 @@ extern NetNet*crop_to_width(Design*des, NetNet*n, unsigned w);
extern NetNet*add_to_net(Design*des, NetNet*sig, long val); extern NetNet*add_to_net(Design*des, NetNet*sig, long val);
extern NetNet*sub_net_from(Design*des, NetScope*scope, long val, NetNet*sig); extern NetNet*sub_net_from(Design*des, NetScope*scope, long val, NetNet*sig);
/*
* These functions make various sorts of expressions, given operands
* of certain type. The order of the operands is preserved in cases
* where order matters.
*
* make_add_expr
* Make a NetEBAdd expression with <expr> the first argument and
* <val> the second. This may get turned into a subtract if <val> is
* less than zero. If val is exactly zero, then return <expr> as is.
*
* make_sub_expr
* Make a NetEBAdd(subtract) node that subtracts the given
* expression from the integer value.
*/
extern NetExpr*make_add_expr(NetExpr*expr, long val);
extern NetExpr*make_sub_expr(long val, NetExpr*expr);
/* /*
* Make a NetEConst object that contains only X bits. * Make a NetEConst object that contains only X bits.
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1999-2009 Stephen Williams (steve@icarus.com) * Copyright (c) 1999-2010 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -131,14 +131,12 @@ void nodangle_f::signal(Design*des, NetNet*sig)
if (sig->get_refs() > 0) if (sig->get_refs() > 0)
return; return;
/* Cannot delete the ports of tasks or functions. There are /* Cannot delete the ports of tasks, functions or modules. There
too many places where they are referenced. */ are too many places where they are referenced. */
if ((sig->port_type() != NetNet::NOT_A_PORT) if ((sig->port_type() != NetNet::NOT_A_PORT) &&
&& (sig->scope()->type() == NetScope::TASK)) ((sig->scope()->type() == NetScope::TASK) ||
return; (sig->scope()->type() == NetScope::FUNC) ||
(sig->scope()->type() == NetScope::MODULE)))
if ((sig->port_type() != NetNet::NOT_A_PORT)
&& (sig->scope()->type() == NetScope::FUNC))
return; return;
/* Can't delete ports of cells. */ /* Can't delete ports of cells. */

View File

@ -2052,7 +2052,7 @@ local_timeunit_prec_decl
module : attribute_list_opt module_start IDENTIFIER module : attribute_list_opt module_start IDENTIFIER
{ pform_startmodule($3, @2.text, @2.first_line, $1); } { pform_startmodule($3, @2.text, @2.first_line, $1); }
module_parameter_port_list_opt module_parameter_port_list_opt
module_port_list_opt module_port_list_opt
module_attribute_foreign ';' module_attribute_foreign ';'
{ pform_module_set_ports($6); } { pform_module_set_ports($6); }
local_timeunit_prec_decl_opt local_timeunit_prec_decl_opt

View File

@ -78,7 +78,7 @@ extern bool have_timeunit_decl;
extern bool have_timeprec_decl; extern bool have_timeprec_decl;
/* /*
* Export there functions because we have to generate PENumber class * Export these functions because we have to generate PENumber class
* in pform.cc for user defparam definition from command file. * in pform.cc for user defparam definition from command file.
*/ */
extern verinum*make_unsized_dec(const char*txt); extern verinum*make_unsized_dec(const char*txt);

View File

@ -62,10 +62,10 @@ void parm_to_defparam_list(const string&param)
key = strdup(param.substr(0, off).c_str()); key = strdup(param.substr(0, off).c_str());
value = strdup(param.substr(off+1).c_str()); value = strdup(param.substr(off+1).c_str());
} }
// Resolve hierarchical name for defparam. Remember // Resolve hierarchical name for defparam. Remember
// to deal with bit select for generate scopes. Bit // to deal with bit select for generate scopes. Bit
// select expression should be constant interger. // select expression should be constant integer.
pform_name_t name; pform_name_t name;
char *nkey = key; char *nkey = key;
char *ptr = strchr(key, '.'); char *ptr = strchr(key, '.');
@ -109,7 +109,7 @@ void parm_to_defparam_list(const string&param)
ptr = strchr(nkey, '.'); ptr = strchr(nkey, '.');
} }
name.push_back(name_component_t(lex_strings.make(nkey))); name.push_back(name_component_t(lex_strings.make(nkey)));
// Resolve value to PExpr class. Should support all kind of constant // Resolve value to PExpr class. Should support all kind of constant
// format including based number, dec number, real number and string. // format including based number, dec number, real number and string.
if (*value == '"') { // string type if (*value == '"') { // string type
@ -127,13 +127,13 @@ void parm_to_defparam_list(const string&param)
cerr << "<command line>: error: missing close quote of string for defparam: " << name << endl; cerr << "<command line>: error: missing close quote of string for defparam: " << name << endl;
else if (*(buf_ptr+1) != 0) { // '"' appears within string with no escape else if (*(buf_ptr+1) != 0) { // '"' appears within string with no escape
cerr << buf_ptr << endl; cerr << buf_ptr << endl;
cerr << "<command line>: error: \'\"\' appears within string value for defparam: " << name cerr << "<command line>: error: \'\"\' appears within string value for defparam: " << name
<< ". Ignore characters after \'\"\'" << endl; << ". Ignore characters after \'\"\'" << endl;
} }
*buf_ptr = '\0'; *buf_ptr = '\0';
buf_ptr = buf+1; buf_ptr = buf+1;
// Remember to use 'new' to allocate string for PEString // Remember to use 'new' to allocate string for PEString
// because 'delete' is used by its destructor. // because 'delete' is used by its destructor.
char *nchar = strcpy(new char [strlen(buf_ptr)+1], buf_ptr); char *nchar = strcpy(new char [strlen(buf_ptr)+1], buf_ptr);
PExpr* ndec = new PEString(nchar); PExpr* ndec = new PEString(nchar);
@ -144,7 +144,7 @@ void parm_to_defparam_list(const string&param)
char *num = strchr(value, '\''); char *num = strchr(value, '\'');
if (num != 0) { if (num != 0) {
verinum *val; verinum *val;
// BASED_NUMBER, somthing like - scope.parameter='b11 // BASED_NUMBER, something like - scope.parameter='b11
// make sure to check 'h' first because 'b'&'d' may be included // make sure to check 'h' first because 'b'&'d' may be included
// in hex format // in hex format
if (strchr(num, 'h') || strchr(num, 'H')) if (strchr(num, 'h') || strchr(num, 'H'))
@ -165,17 +165,17 @@ void parm_to_defparam_list(const string&param)
free(value); free(value);
return; return;
} }
// BASED_NUMBER with size, something like - scope.parameter=2'b11 // BASED_NUMBER with size, something like - scope.parameter=2'b11
if (num != value) { if (num != value) {
*num = 0; *num = 0;
verinum *siz = make_unsized_dec(value); verinum *siz = make_unsized_dec(value);
val = pform_verinum_with_size(siz, val, "<command line>", 0); val = pform_verinum_with_size(siz, val, "<command line>", 0);
} }
PExpr* ndec = new PENumber(val); PExpr* ndec = new PENumber(val);
Module::user_defparms.push_back( make_pair(name, ndec) ); Module::user_defparms.push_back( make_pair(name, ndec) );
} }
else { else {
// REALTIME, something like - scope.parameter=1.22 or scope.parameter=1e2 // REALTIME, something like - scope.parameter=1.22 or scope.parameter=1e2
@ -799,7 +799,7 @@ void pform_endmodule(const char*name, bool inside_celldefine,
tp_local_flag = false; tp_local_flag = false;
} }
static void pform_add_genvar(const struct vlltype&li, const perm_string&name, static void pform_add_genvar(const struct vlltype&li, const perm_string&name,
map<perm_string,LineInfo*>&genvars) map<perm_string,LineInfo*>&genvars)
{ {
LineInfo*lni = new LineInfo(); LineInfo*lni = new LineInfo();

View File

@ -418,7 +418,7 @@ extern PExpr* pform_make_branch_probe_expression(const struct vlltype&loc,
extern PExpr* pform_make_branch_probe_expression(const struct vlltype&loc, extern PExpr* pform_make_branch_probe_expression(const struct vlltype&loc,
char*name, char*branch); char*name, char*branch);
/* /*
* Parse configuration file with format <key>=<value>, where key * Parse configuration file with format <key>=<value>, where key
* is the hierarchical name of a valid parameter name and value * is the hierarchical name of a valid parameter name and value
* is the value user wants to assign to. The value should be constant. * is the value user wants to assign to. The value should be constant.

View File

@ -61,7 +61,7 @@ NetScope*symbol_search(const LineInfo*li, Design*des, NetScope*scope,
cerr << li->get_fileline() << ": error: Hierarchical " cerr << li->get_fileline() << ": error: Hierarchical "
"reference to automatically allocated item " "reference to automatically allocated item "
"`" << key << "' in path `" << path << "'" << endl; "`" << key << "' in path `" << path << "'" << endl;
des->errors += 1; des->errors += 1;
} }
hier_path = true; hier_path = true;

View File

@ -50,7 +50,7 @@ dep:
mv $*.d dep mv $*.d dep
O = vhdl.o state.o vhdl_element.o vhdl_type.o vhdl_syntax.o scope.o process.o \ O = vhdl.o state.o vhdl_element.o vhdl_type.o vhdl_syntax.o scope.o process.o \
stmt.o expr.o lpm.o support.o cast.o logic.o stmt.o expr.o lpm.o display.o support.o cast.o logic.o
ifeq (@WIN32@,yes) ifeq (@WIN32@,yes)
TGTLDFLAGS=-L.. -livl TGTLDFLAGS=-L.. -livl
@ -72,7 +72,7 @@ stamp-vhdl_config-h: $(srcdir)/vhdl_config.h.in ../config.status
vhdl_config.h: stamp-vhdl_config-h vhdl_config.h: stamp-vhdl_config-h
clean: clean:
rm -rf $(O) dep vhdl.tgt rm -rf $(O) dep vhdl.tgt
distclean: clean distclean: clean
rm -f Makefile config.log rm -f Makefile config.log

View File

@ -39,7 +39,7 @@ vhdl_expr *vhdl_expr::cast(const vhdl_type *to)
// we can't generate any type conversion code // we can't generate any type conversion code
if (NULL == type_) if (NULL == type_)
return this; return this;
if (to->get_name() == type_->get_name()) { if (to->get_name() == type_->get_name()) {
if (to->get_width() == type_->get_width()) if (to->get_width() == type_->get_width())
return this; // Identical return this; // Identical
@ -58,8 +58,6 @@ vhdl_expr *vhdl_expr::cast(const vhdl_type *to)
return to_vector(to->get_name(), to->get_width()); return to_vector(to->get_name(), to->get_width());
case VHDL_TYPE_STD_LOGIC: case VHDL_TYPE_STD_LOGIC:
return to_std_logic(); return to_std_logic();
case VHDL_TYPE_STRING:
return to_string();
case VHDL_TYPE_STD_ULOGIC: case VHDL_TYPE_STD_ULOGIC:
return to_std_ulogic(); return to_std_ulogic();
default: default:
@ -81,7 +79,7 @@ vhdl_expr *vhdl_expr::to_vector(vhdl_type_name_t name, int w)
vhdl_bit_spec_expr *bs = vhdl_bit_spec_expr *bs =
new vhdl_bit_spec_expr(new vhdl_type(name, w - 1, 0), others); new vhdl_bit_spec_expr(new vhdl_type(name, w - 1, 0), others);
bs->add_bit(0, this); bs->add_bit(0, this);
return bs; return bs;
} }
else { else {
@ -91,11 +89,11 @@ vhdl_expr *vhdl_expr::to_vector(vhdl_type_name_t name, int w)
vhdl_type *t = new vhdl_type(name, w - 1, 0); vhdl_type *t = new vhdl_type(name, w - 1, 0);
vhdl_fcall *conv = new vhdl_fcall(t->get_string().c_str(), t); vhdl_fcall *conv = new vhdl_fcall(t->get_string().c_str(), t);
conv->add_expr(this); conv->add_expr(this);
if (w != type_->get_width()) if (w != type_->get_width())
return conv->resize(w); return conv->resize(w);
else else
return conv; return conv;
} }
} }
@ -112,29 +110,10 @@ vhdl_expr *vhdl_expr::to_integer()
} }
else else
conv = new vhdl_fcall("To_Integer", vhdl_type::integer()); conv = new vhdl_fcall("To_Integer", vhdl_type::integer());
conv->add_expr(this);
return conv;
}
vhdl_expr *vhdl_expr::to_string() conv->add_expr(this);
{
bool numeric = type_->get_name() == VHDL_TYPE_UNSIGNED return conv;
|| type_->get_name() == VHDL_TYPE_SIGNED;
if (numeric) {
vhdl_fcall *image = new vhdl_fcall("integer'image", vhdl_type::string());
image->add_expr(this->cast(vhdl_type::integer()));
return image;
}
else {
// Assume type'image exists
vhdl_fcall *image = new vhdl_fcall(type_->get_string() + "'image",
vhdl_type::string());
image->add_expr(this);
return image;
}
} }
/* /*
@ -151,7 +130,7 @@ vhdl_expr *vhdl_expr::to_boolean()
else if (type_->get_name() == VHDL_TYPE_UNSIGNED) { else if (type_->get_name() == VHDL_TYPE_UNSIGNED) {
// Need to use a support function for this conversion // Need to use a support function for this conversion
require_support_function(SF_UNSIGNED_TO_BOOLEAN); require_support_function(SF_UNSIGNED_TO_BOOLEAN);
vhdl_fcall *conv = vhdl_fcall *conv =
new vhdl_fcall(support_function::function_name(SF_UNSIGNED_TO_BOOLEAN), new vhdl_fcall(support_function::function_name(SF_UNSIGNED_TO_BOOLEAN),
vhdl_type::boolean()); vhdl_type::boolean());
@ -160,7 +139,7 @@ vhdl_expr *vhdl_expr::to_boolean()
} }
else if (type_->get_name() == VHDL_TYPE_SIGNED) { else if (type_->get_name() == VHDL_TYPE_SIGNED) {
require_support_function(SF_SIGNED_TO_BOOLEAN); require_support_function(SF_SIGNED_TO_BOOLEAN);
vhdl_fcall *conv = vhdl_fcall *conv =
new vhdl_fcall(support_function::function_name(SF_SIGNED_TO_BOOLEAN), new vhdl_fcall(support_function::function_name(SF_SIGNED_TO_BOOLEAN),
vhdl_type::boolean()); vhdl_type::boolean());
@ -178,12 +157,12 @@ vhdl_expr *vhdl_expr::to_std_logic()
{ {
if (type_->get_name() == VHDL_TYPE_BOOLEAN) { if (type_->get_name() == VHDL_TYPE_BOOLEAN) {
require_support_function(SF_BOOLEAN_TO_LOGIC); require_support_function(SF_BOOLEAN_TO_LOGIC);
vhdl_fcall *ah = vhdl_fcall *ah =
new vhdl_fcall(support_function::function_name(SF_BOOLEAN_TO_LOGIC), new vhdl_fcall(support_function::function_name(SF_BOOLEAN_TO_LOGIC),
vhdl_type::std_logic()); vhdl_type::std_logic());
ah->add_expr(this); ah->add_expr(this);
return ah; return ah;
} }
else if (type_->get_name() == VHDL_TYPE_SIGNED) { else if (type_->get_name() == VHDL_TYPE_SIGNED) {
@ -217,7 +196,7 @@ vhdl_expr *vhdl_expr::to_std_ulogic()
f->add_expr(this); f->add_expr(this);
return f; return f;
} }
else else
assert(false); assert(false);
} }
@ -240,11 +219,11 @@ vhdl_expr *vhdl_expr::resize(int newwidth)
vhdl_binop_expr* concat = vhdl_binop_expr* concat =
new vhdl_binop_expr(zeros, VHDL_BINOP_CONCAT, this, new vhdl_binop_expr(zeros, VHDL_BINOP_CONCAT, this,
vhdl_type::nunsigned(newwidth)); vhdl_type::nunsigned(newwidth));
return concat; return concat;
} }
else else
return this; // Doesn't make sense to resize non-vector type return this; // Doesn't make sense to resize non-vector type
vhdl_fcall *resizef = new vhdl_fcall("Resize", rtype); vhdl_fcall *resizef = new vhdl_fcall("Resize", rtype);
resizef->add_expr(this); resizef->add_expr(this);
resizef->add_expr(new vhdl_const_int(newwidth)); resizef->add_expr(new vhdl_const_int(newwidth));
@ -288,10 +267,10 @@ vhdl_expr *vhdl_const_bits::to_std_logic()
// VHDL won't let us cast directly between a vector and // VHDL won't let us cast directly between a vector and
// a scalar type // a scalar type
// But we don't need to here as we have the bits available // But we don't need to here as we have the bits available
// Take the least significant bit // Take the least significant bit
char lsb = value_[0]; char lsb = value_[0];
return new vhdl_const_bit(lsb); return new vhdl_const_bit(lsb);
} }
@ -301,14 +280,14 @@ char vhdl_const_bits::sign_bit() const
} }
vhdl_expr *vhdl_const_bits::to_vector(vhdl_type_name_t name, int w) vhdl_expr *vhdl_const_bits::to_vector(vhdl_type_name_t name, int w)
{ {
if (name == VHDL_TYPE_STD_LOGIC_VECTOR) { if (name == VHDL_TYPE_STD_LOGIC_VECTOR) {
// Don't need to do anything // Don't need to do anything
return this; return this;
} }
else if (name == VHDL_TYPE_SIGNED || name == VHDL_TYPE_UNSIGNED) { else if (name == VHDL_TYPE_SIGNED || name == VHDL_TYPE_UNSIGNED) {
// Extend with sign bit // Extend with sign bit
value_.resize(w, sign_bit()); value_.resize(w, sign_bit());
return this; return this;
} }
assert(false); assert(false);
@ -325,8 +304,8 @@ vhdl_expr *vhdl_const_bits::resize(int w)
// Rather than generating a call to Resize, when can just sign-extend // Rather than generating a call to Resize, when can just sign-extend
// the bits here. As well as looking better, this avoids any ambiguity // the bits here. As well as looking better, this avoids any ambiguity
// between which of the signed/unsigned versions of Resize to use. // between which of the signed/unsigned versions of Resize to use.
value_.resize(w, sign_bit()); value_.resize(w, sign_bit());
return this; return this;
} }

200
tgt-vhdl/display.cc Normal file
View File

@ -0,0 +1,200 @@
/*
* VHDL implementation of $display.
*
* Copyright (C) 2008-2009 Nick Gasson (nick@nickg.me.uk)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "vhdl_target.h"
#include <iostream>
#include <cstring>
#include <cassert>
#include <cctype>
#include <sstream>
static const char *DISPLAY_LINE = "Verilog_Display_Line";
/*
* Write a VHDL expression into the current display line.
*/
static void display_write(stmt_container *container, vhdl_expr *expr)
{
vhdl_pcall_stmt *write = new vhdl_pcall_stmt("Write");
vhdl_var_ref *ref =
new vhdl_var_ref(DISPLAY_LINE, vhdl_type::line());
write->add_expr(ref);
vhdl_type_name_t type = expr->get_type()->get_name();
if (type == VHDL_TYPE_SIGNED || type == VHDL_TYPE_UNSIGNED) {
vhdl_type integer(VHDL_TYPE_INTEGER);
write->add_expr(expr->cast(&integer));
}
else if (type != VHDL_TYPE_STRING) {
// Need to add a call to Type'Image for types not
// supported by std.textio
std::string name(expr->get_type()->get_string());
name += "'Image";
vhdl_fcall *cast
= new vhdl_fcall(name.c_str(), vhdl_type::string());
cast->add_expr(expr);
write->add_expr(cast);
}
else
write->add_expr(expr);
container->add_stmt(write);
}
/*
* Write the value of DISPLAY_LINE to the output.
*/
static void display_line(stmt_container *container)
{
vhdl_pcall_stmt *write_line = new vhdl_pcall_stmt("WriteLine");
vhdl_var_ref *output_ref =
new vhdl_var_ref("std.textio.Output", new vhdl_type(VHDL_TYPE_FILE));
write_line->add_expr(output_ref);
vhdl_var_ref *ref =
new vhdl_var_ref(DISPLAY_LINE, vhdl_type::line());
write_line->add_expr(ref);
container->add_stmt(write_line);
}
/*
* Parse an octal escape sequence.
*/
static char parse_octal(const char *p)
{
assert(*p && *(p+1) && *(p+2));
assert(isdigit(*p) && isdigit(*(p+1)) && isdigit(*(p+1)));
return (*p - '0') * 64
+ (*(p+1) - '0') * 8
+ (*(p+2) - '0') * 1;
}
static void flush_string(std::ostringstream &ss, stmt_container *container)
{
display_write(container, new vhdl_const_string(ss.str().c_str()));
// Clear the stream
ss.str("");
}
// This should display the hierarchical module name, but we don't support
// this in VHDL. So just emit a warning.
static void display_m(stmt_container* container)
{
cerr << "Warning: no VHDL translation for %m format code" << endl;
}
/*
* Generate VHDL for the $display system task.
* This is implemented using the functions in std.textio. Each
* parameter is written to a line variable in the process and
* then the line is written to the special variable `Output'
* (which represents the console). Subsequent $displays will
* use the same line variable.
*
* It's possible, although quite unlikely, that there will be
* name collision with an existing variable called
* `Verilog_Display_Line' -- do something about this?
*/
int draw_stask_display(vhdl_procedural *proc, stmt_container *container,
ivl_statement_t stmt, bool newline)
{
if (!proc->get_scope()->have_declared(DISPLAY_LINE)) {
vhdl_var_decl *line_var =
new vhdl_var_decl(DISPLAY_LINE, vhdl_type::line());
line_var->set_comment("For generating $display output");
proc->get_scope()->add_decl(line_var);
}
// Write the data into the line
int count = ivl_stmt_parm_count(stmt), i = 0;
while (i < count) {
// $display may have an empty parameter, in which case
// the expression will be null
// The behaviour here seems to be to output a space
ivl_expr_t net = ivl_stmt_parm(stmt, i++);
if (net == NULL) {
display_write(container, new vhdl_const_string(" "));
continue;
}
if (ivl_expr_type(net) == IVL_EX_STRING) {
ostringstream ss;
for (const char *p = ivl_expr_string(net); *p; p++) {
if (*p == '\\') {
// Octal escape
char ch = parse_octal(p+1);
if (ch == '\n') {
flush_string(ss, container);
display_line(container);
}
else
ss << ch;
p += 3;
}
else if (*p == '%' && *(++p) != '%') {
flush_string(ss, container);
// Skip over width for now
while (isdigit(*p)) ++p;
switch (*p) {
case 'm':
display_m(container);
break;
default:
{
assert(i < count);
ivl_expr_t netp = ivl_stmt_parm(stmt, i++);
assert(netp);
vhdl_expr *base = translate_expr(netp);
if (NULL == base)
return 1;
display_write(container, base);
}
}
}
else
ss << *p;
}
// Call Write on any non-empty string data left in the buffer
if (!ss.str().empty())
display_write(container, new vhdl_const_string(ss.str().c_str()));
}
else {
vhdl_expr *base = translate_expr(net);
if (NULL == base)
return 1;
display_write(container, base);
}
}
if (newline)
display_line(container);
return 0;
}

View File

@ -35,7 +35,7 @@ static vhdl_expr *change_signedness(vhdl_expr *e, bool issigned)
int msb = e->get_type()->get_msb(); int msb = e->get_type()->get_msb();
int lsb = e->get_type()->get_lsb(); int lsb = e->get_type()->get_lsb();
vhdl_type u(issigned ? VHDL_TYPE_SIGNED : VHDL_TYPE_UNSIGNED, msb, lsb); vhdl_type u(issigned ? VHDL_TYPE_SIGNED : VHDL_TYPE_UNSIGNED, msb, lsb);
return e->cast(&u); return e->cast(&u);
} }
@ -44,9 +44,9 @@ static vhdl_expr *change_signedness(vhdl_expr *e, bool issigned)
* same signedness as the Verilog expression vl_e. * same signedness as the Verilog expression vl_e.
*/ */
static vhdl_expr *correct_signedness(vhdl_expr *vhd_e, ivl_expr_t vl_e) static vhdl_expr *correct_signedness(vhdl_expr *vhd_e, ivl_expr_t vl_e)
{ {
bool should_be_signed = ivl_expr_signed(vl_e) != 0; bool should_be_signed = ivl_expr_signed(vl_e) != 0;
if (vhd_e->get_type()->get_name() == VHDL_TYPE_UNSIGNED if (vhd_e->get_type()->get_name() == VHDL_TYPE_UNSIGNED
&& should_be_signed) { && should_be_signed) {
//operand->print(); //operand->print();
@ -69,7 +69,7 @@ static vhdl_expr *correct_signedness(vhdl_expr *vhd_e, ivl_expr_t vl_e)
* Convert a constant Verilog string to a constant VHDL string. * Convert a constant Verilog string to a constant VHDL string.
*/ */
static vhdl_expr *translate_string(ivl_expr_t e) static vhdl_expr *translate_string(ivl_expr_t e)
{ {
// TODO: May need to inspect or escape parts of this // TODO: May need to inspect or escape parts of this
const char *str = ivl_expr_string(e); const char *str = ivl_expr_string(e);
return new vhdl_const_string(str); return new vhdl_const_string(str);
@ -82,12 +82,12 @@ static vhdl_expr *translate_string(ivl_expr_t e)
static vhdl_var_ref *translate_signal(ivl_expr_t e) static vhdl_var_ref *translate_signal(ivl_expr_t e)
{ {
ivl_signal_t sig = ivl_expr_signal(e); ivl_signal_t sig = ivl_expr_signal(e);
const vhdl_scope *scope = find_scope_for_signal(sig); const vhdl_scope *scope = find_scope_for_signal(sig);
assert(scope); assert(scope);
const char *renamed = get_renamed_signal(sig).c_str(); const char *renamed = get_renamed_signal(sig).c_str();
vhdl_decl *decl = scope->get_decl(renamed); vhdl_decl *decl = scope->get_decl(renamed);
assert(decl); assert(decl);
@ -102,7 +102,7 @@ static vhdl_var_ref *translate_signal(ivl_expr_t e)
vhdl_var_ref *ref = vhdl_var_ref *ref =
new vhdl_var_ref(renamed, new vhdl_type(*decl->get_type())); new vhdl_var_ref(renamed, new vhdl_type(*decl->get_type()));
ivl_expr_t off; ivl_expr_t off;
if (ivl_signal_array_count(sig) > 0 && (off = ivl_expr_oper1(e))) { if (ivl_signal_array_count(sig) > 0 && (off = ivl_expr_oper1(e))) {
// Select from an array // Select from an array
@ -152,7 +152,7 @@ static vhdl_expr *translate_reduction(support_function_t f, bool neg,
vhdl_fcall *fcall = vhdl_fcall *fcall =
new vhdl_fcall(support_function::function_name(f), new vhdl_fcall(support_function::function_name(f),
vhdl_type::std_logic()); vhdl_type::std_logic());
vhdl_type std_logic_vector(VHDL_TYPE_STD_LOGIC_VECTOR); vhdl_type std_logic_vector(VHDL_TYPE_STD_LOGIC_VECTOR);
fcall->add_expr(operand->cast(&std_logic_vector)); fcall->add_expr(operand->cast(&std_logic_vector));
@ -173,7 +173,7 @@ static vhdl_expr *translate_unary(ivl_expr_t e)
return NULL; return NULL;
operand = correct_signedness(operand, e); operand = correct_signedness(operand, e);
char opcode = ivl_expr_opcode(e); char opcode = ivl_expr_opcode(e);
switch (opcode) { switch (opcode) {
case '!': case '!':
@ -234,7 +234,7 @@ static vhdl_expr *translate_relation(vhdl_expr *lhs, vhdl_expr *rhs,
// Generate any necessary casts // Generate any necessary casts
// Arbitrarily, the RHS is casted to the type of the LHS // Arbitrarily, the RHS is casted to the type of the LHS
vhdl_expr *r_cast = rhs->cast(lhs->get_type()); vhdl_expr *r_cast = rhs->cast(lhs->get_type());
return new vhdl_binop_expr(lhs, op, r_cast, vhdl_type::boolean()); return new vhdl_binop_expr(lhs, op, r_cast, vhdl_type::boolean());
} }
@ -311,7 +311,7 @@ static vhdl_expr *translate_binary(ivl_expr_t e)
vhdl_expr *lhs = translate_expr(ivl_expr_oper1(e)); vhdl_expr *lhs = translate_expr(ivl_expr_oper1(e));
if (NULL == lhs) if (NULL == lhs)
return NULL; return NULL;
vhdl_expr *rhs = translate_expr(ivl_expr_oper2(e)); vhdl_expr *rhs = translate_expr(ivl_expr_oper2(e));
if (NULL == rhs) if (NULL == rhs)
return NULL; return NULL;
@ -319,7 +319,7 @@ static vhdl_expr *translate_binary(ivl_expr_t e)
int lwidth = lhs->get_type()->get_width(); int lwidth = lhs->get_type()->get_width();
int rwidth = rhs->get_type()->get_width(); int rwidth = rhs->get_type()->get_width();
int result_width = ivl_expr_width(e); int result_width = ivl_expr_width(e);
// For === and !== we need to compare std_logic_vectors // For === and !== we need to compare std_logic_vectors
// rather than signeds // rather than signeds
vhdl_type std_logic_vector(VHDL_TYPE_STD_LOGIC_VECTOR, result_width-1, 0); vhdl_type std_logic_vector(VHDL_TYPE_STD_LOGIC_VECTOR, result_width-1, 0);
@ -328,7 +328,7 @@ static vhdl_expr *translate_binary(ivl_expr_t e)
bool vectorop = bool vectorop =
(ltype == VHDL_TYPE_SIGNED || ltype == VHDL_TYPE_UNSIGNED) && (ltype == VHDL_TYPE_SIGNED || ltype == VHDL_TYPE_UNSIGNED) &&
(rtype == VHDL_TYPE_SIGNED || rtype == VHDL_TYPE_UNSIGNED); (rtype == VHDL_TYPE_SIGNED || rtype == VHDL_TYPE_UNSIGNED);
// May need to resize the left or right hand side or change the // May need to resize the left or right hand side or change the
// signedness // signedness
if (vectorop) { if (vectorop) {
@ -425,7 +425,7 @@ static vhdl_expr *translate_binary(ivl_expr_t e)
result = translate_shift(lhs, rhs, VHDL_BINOP_SRA); result = translate_shift(lhs, rhs, VHDL_BINOP_SRA);
else else
result = translate_shift(lhs, rhs, VHDL_BINOP_SR); result = translate_shift(lhs, rhs, VHDL_BINOP_SR);
break; break;
case '^': case '^':
result = translate_numeric(lhs, rhs, VHDL_BINOP_XOR); result = translate_numeric(lhs, rhs, VHDL_BINOP_XOR);
break; break;
@ -463,7 +463,7 @@ static vhdl_expr *translate_select(ivl_expr_t e)
return NULL; return NULL;
ivl_expr_t o2 = ivl_expr_oper2(e); ivl_expr_t o2 = ivl_expr_oper2(e);
if (o2) { if (o2) {
vhdl_expr *base = translate_expr(ivl_expr_oper2(e)); vhdl_expr *base = translate_expr(ivl_expr_oper2(e));
if (NULL == base) if (NULL == base)
return NULL; return NULL;
@ -477,7 +477,7 @@ static vhdl_expr *translate_select(ivl_expr_t e)
new vhdl_type(*from->get_type())); new vhdl_type(*from->get_type()));
} }
else if (from_var_ref->get_type()->get_name() != VHDL_TYPE_STD_LOGIC) { else if (from_var_ref->get_type()->get_name() != VHDL_TYPE_STD_LOGIC) {
// We can use the more idomatic VHDL slice notation on a // We can use the more idiomatic VHDL slice notation on a
// single variable reference // single variable reference
vhdl_type integer(VHDL_TYPE_INTEGER); vhdl_type integer(VHDL_TYPE_INTEGER);
from_var_ref->set_slice(base->cast(&integer), ivl_expr_width(e) - 1); from_var_ref->set_slice(base->cast(&integer), ivl_expr_width(e) - 1);
@ -528,7 +528,7 @@ static vhdl_expr *translate_ufunc(ivl_expr_t e)
const char *funcname = ivl_scope_tname(defscope); const char *funcname = ivl_scope_tname(defscope);
vhdl_type *rettype = vhdl_type *rettype =
vhdl_type::type_for(ivl_expr_width(e), ivl_expr_signed(e) != 0); vhdl_type::type_for(ivl_expr_width(e), ivl_expr_signed(e) != 0);
vhdl_fcall *fcall = new vhdl_fcall(funcname, rettype); vhdl_fcall *fcall = new vhdl_fcall(funcname, rettype);
@ -539,18 +539,18 @@ static vhdl_expr *translate_ufunc(ivl_expr_t e)
delete fcall; delete fcall;
return NULL; return NULL;
} }
// Ensure the parameter has the correct VHDL type // Ensure the parameter has the correct VHDL type
// Parameter number is i + 1 since 0th parameter is return value // Parameter number is i + 1 since 0th parameter is return value
ivl_signal_t param_sig = ivl_scope_port(defscope, i + 1); ivl_signal_t param_sig = ivl_scope_port(defscope, i + 1);
vhdl_type *param_type = vhdl_type *param_type =
vhdl_type::type_for(ivl_signal_width(param_sig), vhdl_type::type_for(ivl_signal_width(param_sig),
ivl_signal_signed(param_sig) != 0); ivl_signal_signed(param_sig) != 0);
fcall->add_expr(param->cast(param_type)); fcall->add_expr(param->cast(param_type));
delete param_type; delete param_type;
} }
return fcall; return fcall;
} }
@ -565,7 +565,7 @@ static vhdl_expr *translate_ternary(ivl_expr_t e)
sf = SF_TERNARY_SIGNED; sf = SF_TERNARY_SIGNED;
else else
sf = SF_TERNARY_UNSIGNED; sf = SF_TERNARY_UNSIGNED;
require_support_function(sf); require_support_function(sf);
vhdl_expr *test = translate_expr(ivl_expr_oper1(e)); vhdl_expr *test = translate_expr(ivl_expr_oper1(e));
@ -576,20 +576,20 @@ static vhdl_expr *translate_ternary(ivl_expr_t e)
vhdl_type boolean(VHDL_TYPE_BOOLEAN); vhdl_type boolean(VHDL_TYPE_BOOLEAN);
test = test->cast(&boolean); test = test->cast(&boolean);
vhdl_fcall *fcall = vhdl_fcall *fcall =
new vhdl_fcall(support_function::function_name(sf), new vhdl_fcall(support_function::function_name(sf),
vhdl_type::type_for(width, issigned)); vhdl_type::type_for(width, issigned));
fcall->add_expr(test); fcall->add_expr(test);
fcall->add_expr(true_part); fcall->add_expr(true_part);
fcall->add_expr(false_part); fcall->add_expr(false_part);
return fcall; return fcall;
} }
static vhdl_expr *translate_concat(ivl_expr_t e) static vhdl_expr *translate_concat(ivl_expr_t e)
{ {
vhdl_type *rtype = vhdl_type *rtype =
vhdl_type::type_for(ivl_expr_width(e), ivl_expr_signed(e) != 0); vhdl_type::type_for(ivl_expr_width(e), ivl_expr_signed(e) != 0);
vhdl_binop_expr *concat = new vhdl_binop_expr(VHDL_BINOP_CONCAT, rtype); vhdl_binop_expr *concat = new vhdl_binop_expr(VHDL_BINOP_CONCAT, rtype);
@ -716,11 +716,11 @@ vhdl_expr *translate_time_expr(ivl_expr_t e)
if (time->get_type()->get_name() != VHDL_TYPE_TIME) { if (time->get_type()->get_name() != VHDL_TYPE_TIME) {
vhdl_type integer(VHDL_TYPE_INTEGER); vhdl_type integer(VHDL_TYPE_INTEGER);
time = time->cast(&integer); time = time->cast(&integer);
vhdl_expr *ns1 = scale_time(get_active_entity(), 1); vhdl_expr *ns1 = scale_time(get_active_entity(), 1);
return new vhdl_binop_expr(time, VHDL_BINOP_MULT, ns1, return new vhdl_binop_expr(time, VHDL_BINOP_MULT, ns1,
vhdl_type::time()); vhdl_type::time());
} }
else // Translating IVL_EX_DELAY will always return a time type else // Translating IVL_EX_DELAY will always return a time type
return time; return time;
} }

View File

@ -36,11 +36,11 @@ static vhdl_expr *inputs_to_expr(vhdl_scope *scope, vhdl_binop_t op,
// the program has already been type checked // the program has already been type checked
vhdl_binop_expr *gate = vhdl_binop_expr *gate =
new vhdl_binop_expr(op, vhdl_type::std_logic()); new vhdl_binop_expr(op, vhdl_type::std_logic());
int npins = ivl_logic_pins(log); int npins = ivl_logic_pins(log);
for (int i = 1; i < npins; i++) { for (int i = 1; i < npins; i++) {
ivl_nexus_t input = ivl_logic_pin(log, i); ivl_nexus_t input = ivl_logic_pin(log, i);
gate->add_expr(readable_ref(scope, input)); gate->add_expr(readable_ref(scope, input));
} }
@ -57,7 +57,7 @@ static vhdl_expr *input_to_expr(vhdl_scope *scope, vhdl_unaryop_t op,
assert(input); assert(input);
vhdl_expr *operand = readable_ref(scope, input); vhdl_expr *operand = readable_ref(scope, input);
return new vhdl_unaryop_expr(op, operand, vhdl_type::std_logic()); return new vhdl_unaryop_expr(op, operand, vhdl_type::std_logic());
} }
static void bufif_logic(vhdl_arch *arch, ivl_net_logic_t log, bool if0) static void bufif_logic(vhdl_arch *arch, ivl_net_logic_t log, bool if0)
@ -65,7 +65,7 @@ static void bufif_logic(vhdl_arch *arch, ivl_net_logic_t log, bool if0)
ivl_nexus_t output = ivl_logic_pin(log, 0); ivl_nexus_t output = ivl_logic_pin(log, 0);
vhdl_var_ref *lhs = nexus_to_var_ref(arch->get_scope(), output); vhdl_var_ref *lhs = nexus_to_var_ref(arch->get_scope(), output);
assert(lhs); assert(lhs);
vhdl_expr *val = readable_ref(arch->get_scope(), ivl_logic_pin(log, 1)); vhdl_expr *val = readable_ref(arch->get_scope(), ivl_logic_pin(log, 1));
vhdl_expr *sel = readable_ref(arch->get_scope(), ivl_logic_pin(log, 2)); vhdl_expr *sel = readable_ref(arch->get_scope(), ivl_logic_pin(log, 2));
@ -80,7 +80,7 @@ static void bufif_logic(vhdl_arch *arch, ivl_net_logic_t log, bool if0)
vhdl_binop_t op = if0 ? VHDL_BINOP_EQ : VHDL_BINOP_NEQ; vhdl_binop_t op = if0 ? VHDL_BINOP_EQ : VHDL_BINOP_NEQ;
cmp = new vhdl_binop_expr(sel, op, zero, NULL); cmp = new vhdl_binop_expr(sel, op, zero, NULL);
} }
ivl_signal_t sig = find_signal_named(lhs->get_name(), arch->get_scope()); ivl_signal_t sig = find_signal_named(lhs->get_name(), arch->get_scope());
char zbit; char zbit;
switch (ivl_signal_type(sig)) { switch (ivl_signal_type(sig)) {
@ -107,12 +107,12 @@ static void bufif_logic(vhdl_arch *arch, ivl_net_logic_t log, bool if0)
static void comb_udp_logic(vhdl_arch *arch, ivl_net_logic_t log) static void comb_udp_logic(vhdl_arch *arch, ivl_net_logic_t log)
{ {
ivl_udp_t udp = ivl_logic_udp(log); ivl_udp_t udp = ivl_logic_udp(log);
// As with regular case statements, the expression in a // As with regular case statements, the expression in a
// `with .. select' statement must be "locally static". // `with .. select' statement must be "locally static".
// This is achieved by first combining the inputs into // This is achieved by first combining the inputs into
// a temporary // a temporary
ostringstream ss; ostringstream ss;
ss << ivl_logic_basename(log) << "_Tmp"; ss << ivl_logic_basename(log) << "_Tmp";
int msb = ivl_udp_nin(udp) - 1; int msb = ivl_udp_nin(udp) - 1;
@ -149,11 +149,11 @@ static void comb_udp_logic(vhdl_arch *arch, ivl_net_logic_t log)
// Ensure the select statement completely covers the input space // Ensure the select statement completely covers the input space
// or some strict VHDL compilers will complain // or some strict VHDL compilers will complain
ws->add_default(new vhdl_const_bit('X')); ws->add_default(new vhdl_const_bit('X'));
int nrows = ivl_udp_rows(udp); int nrows = ivl_udp_rows(udp);
for (int i = 0; i < nrows; i++) { for (int i = 0; i < nrows; i++) {
const char *row = ivl_udp_row(udp, i); const char *row = ivl_udp_row(udp, i);
vhdl_expr *value = new vhdl_const_bit(row[nin]); vhdl_expr *value = new vhdl_const_bit(row[nin]);
vhdl_expr *cond = new vhdl_const_bits(row, nin, false); vhdl_expr *cond = new vhdl_const_bits(row, nin, false);
@ -189,11 +189,11 @@ static void seq_udp_logic(vhdl_arch *arch, ivl_net_logic_t log)
int msb = ivl_udp_nin(udp) - 1; int msb = ivl_udp_nin(udp) - 1;
vhdl_type *tmp_type = vhdl_type::std_logic_vector(msb, 0); vhdl_type *tmp_type = vhdl_type::std_logic_vector(msb, 0);
proc->get_scope()->add_decl(new vhdl_var_decl("UDP_Inputs", tmp_type)); proc->get_scope()->add_decl(new vhdl_var_decl("UDP_Inputs", tmp_type));
// Concatenate the inputs into a single expression that can be // Concatenate the inputs into a single expression that can be
// used as the test in a case statement (this can't be inserted // used as the test in a case statement (this can't be inserted
// directly into the case statement due to the requirement that // directly into the case statement due to the requirement that
// the test expression be "locally static") // the test expression be "locally static")
int nin = ivl_udp_nin(udp); int nin = ivl_udp_nin(udp);
vhdl_expr *tmp_rhs = NULL; vhdl_expr *tmp_rhs = NULL;
if (nin == 1) { if (nin == 1) {
@ -217,7 +217,7 @@ static void seq_udp_logic(vhdl_arch *arch, ivl_net_logic_t log)
proc->get_container()->add_stmt proc->get_container()->add_stmt
(new vhdl_assign_stmt(new vhdl_var_ref("UDP_Inputs", NULL), tmp_rhs)); (new vhdl_assign_stmt(new vhdl_var_ref("UDP_Inputs", NULL), tmp_rhs));
arch->add_stmt(proc); arch->add_stmt(proc);
} }
@ -273,18 +273,18 @@ void draw_logic(vhdl_arch *arch, ivl_net_logic_t log)
udp_logic(arch, log); udp_logic(arch, log);
break; break;
default: default:
{ {
// The output is always pin zero // The output is always pin zero
ivl_nexus_t output = ivl_logic_pin(log, 0); ivl_nexus_t output = ivl_logic_pin(log, 0);
vhdl_var_ref *lhs = nexus_to_var_ref(arch->get_scope(), output); vhdl_var_ref *lhs = nexus_to_var_ref(arch->get_scope(), output);
vhdl_expr *rhs = translate_logic_inputs(arch->get_scope(), log); vhdl_expr *rhs = translate_logic_inputs(arch->get_scope(), log);
vhdl_cassign_stmt *ass = new vhdl_cassign_stmt(lhs, rhs); vhdl_cassign_stmt *ass = new vhdl_cassign_stmt(lhs, rhs);
ivl_expr_t delay = ivl_logic_delay(log, 1); ivl_expr_t delay = ivl_logic_delay(log, 1);
if (delay) if (delay)
ass->set_after(translate_time_expr(delay)); ass->set_after(translate_time_expr(delay));
arch->add_stmt(ass); arch->add_stmt(ass);
} }
} }

View File

@ -47,7 +47,7 @@ static vhdl_expr *concat_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm)
vhdl_type::type_for(ivl_lpm_width(lpm), ivl_lpm_signed(lpm) != 0); vhdl_type::type_for(ivl_lpm_width(lpm), ivl_lpm_signed(lpm) != 0);
vhdl_binop_expr *expr = vhdl_binop_expr *expr =
new vhdl_binop_expr(VHDL_BINOP_CONCAT, result_type); new vhdl_binop_expr(VHDL_BINOP_CONCAT, result_type);
for (int i = ivl_lpm_size(lpm) - 1; i >= 0; i--) { for (int i = ivl_lpm_size(lpm) - 1; i >= 0; i--) {
vhdl_expr *e = readable_ref(scope, ivl_lpm_data(lpm, i)); vhdl_expr *e = readable_ref(scope, ivl_lpm_data(lpm, i));
if (NULL == e) { if (NULL == e) {
@ -67,7 +67,7 @@ static vhdl_expr *binop_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm, vhdl_binop
vhdl_type *result_type = vhdl_type *result_type =
vhdl_type::type_for(out_width, ivl_lpm_signed(lpm) != 0); vhdl_type::type_for(out_width, ivl_lpm_signed(lpm) != 0);
vhdl_binop_expr *expr = new vhdl_binop_expr(op, result_type); vhdl_binop_expr *expr = new vhdl_binop_expr(op, result_type);
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
vhdl_expr *e = readable_ref(scope, ivl_lpm_data(lpm, i)); vhdl_expr *e = readable_ref(scope, ivl_lpm_data(lpm, i));
if (NULL == e) { if (NULL == e) {
@ -77,16 +77,16 @@ static vhdl_expr *binop_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm, vhdl_binop
expr->add_expr(e->cast(result_type)); expr->add_expr(e->cast(result_type));
} }
if (op == VHDL_BINOP_MULT) { if (op == VHDL_BINOP_MULT) {
// Need to resize the output to the desired size, // Need to resize the output to the desired size,
// as this does not happen automatically in VHDL // as this does not happen automatically in VHDL
vhdl_fcall *resize = vhdl_fcall *resize =
new vhdl_fcall("Resize", vhdl_type::nsigned(out_width)); new vhdl_fcall("Resize", vhdl_type::nsigned(out_width));
resize->add_expr(expr); resize->add_expr(expr);
resize->add_expr(new vhdl_const_int(out_width)); resize->add_expr(new vhdl_const_int(out_width));
return resize; return resize;
} }
else else
@ -106,7 +106,7 @@ static vhdl_expr *rel_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm, vhdl_binop_t
delete lhs; delete lhs;
return NULL; return NULL;
} }
// Ensure LHS and RHS are the same type // Ensure LHS and RHS are the same type
if (lhs->get_type() != rhs->get_type()) if (lhs->get_type() != rhs->get_type())
rhs = rhs->cast(lhs->get_type()); rhs = rhs->cast(lhs->get_type());
@ -122,20 +122,20 @@ static vhdl_expr *part_select_vp_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm)
vhdl_var_ref *selfrom = readable_ref(scope, ivl_lpm_data(lpm, 0)); vhdl_var_ref *selfrom = readable_ref(scope, ivl_lpm_data(lpm, 0));
if (NULL == selfrom) if (NULL == selfrom)
return NULL; return NULL;
vhdl_expr *off = part_select_base(scope, lpm);; vhdl_expr *off = part_select_base(scope, lpm);;
if (NULL == off) if (NULL == off)
return NULL; return NULL;
if (selfrom->get_type()->get_width() > 1) if (selfrom->get_type()->get_width() > 1)
selfrom->set_slice(off, ivl_lpm_width(lpm) - 1); selfrom->set_slice(off, ivl_lpm_width(lpm) - 1);
return selfrom; return selfrom;
} }
static vhdl_expr *part_select_pv_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm) static vhdl_expr *part_select_pv_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm)
{ {
return readable_ref(scope, ivl_lpm_data(lpm, 0)); return readable_ref(scope, ivl_lpm_data(lpm, 0));
} }
@ -171,13 +171,13 @@ static vhdl_expr *reduction_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm,
require_support_function(f); require_support_function(f);
vhdl_fcall *fcall = new vhdl_fcall(support_function::function_name(f), vhdl_fcall *fcall = new vhdl_fcall(support_function::function_name(f),
vhdl_type::std_logic()); vhdl_type::std_logic());
vhdl_type std_logic_vector(VHDL_TYPE_STD_LOGIC_VECTOR); vhdl_type std_logic_vector(VHDL_TYPE_STD_LOGIC_VECTOR);
fcall->add_expr(ref->cast(&std_logic_vector)); fcall->add_expr(ref->cast(&std_logic_vector));
result = fcall; result = fcall;
} }
if (invert) if (invert)
return new vhdl_unaryop_expr return new vhdl_unaryop_expr
(VHDL_UNARYOP_NOT, result, vhdl_type::std_logic()); (VHDL_UNARYOP_NOT, result, vhdl_type::std_logic());
@ -199,12 +199,12 @@ static vhdl_expr *array_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm)
ivl_signal_t array = ivl_lpm_array(lpm); ivl_signal_t array = ivl_lpm_array(lpm);
if (!seen_signal_before(array)) if (!seen_signal_before(array))
return NULL; return NULL;
const char *renamed = get_renamed_signal(array).c_str(); const char *renamed = get_renamed_signal(array).c_str();
vhdl_decl *adecl = scope->get_decl(renamed); vhdl_decl *adecl = scope->get_decl(renamed);
assert(adecl); assert(adecl);
vhdl_type *atype = new vhdl_type(*adecl->get_type()); vhdl_type *atype = new vhdl_type(*adecl->get_type());
vhdl_expr *select = readable_ref(scope, ivl_lpm_select(lpm)); vhdl_expr *select = readable_ref(scope, ivl_lpm_select(lpm));
@ -212,11 +212,11 @@ static vhdl_expr *array_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm)
delete atype; delete atype;
return NULL; return NULL;
} }
vhdl_var_ref *ref = new vhdl_var_ref(renamed, atype); vhdl_var_ref *ref = new vhdl_var_ref(renamed, atype);
vhdl_type integer(VHDL_TYPE_INTEGER); vhdl_type integer(VHDL_TYPE_INTEGER);
ref->set_slice(select->cast(&integer)); ref->set_slice(select->cast(&integer));
return ref; return ref;
} }
@ -226,8 +226,8 @@ static vhdl_expr *shift_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm,
vhdl_expr *lhs = readable_ref(scope, ivl_lpm_data(lpm, 0)); vhdl_expr *lhs = readable_ref(scope, ivl_lpm_data(lpm, 0));
vhdl_expr *rhs = readable_ref(scope, ivl_lpm_data(lpm, 1)); vhdl_expr *rhs = readable_ref(scope, ivl_lpm_data(lpm, 1));
if (!lhs || !rhs) if (!lhs || !rhs)
return NULL; return NULL;
// The RHS must be an integer // The RHS must be an integer
vhdl_type integer(VHDL_TYPE_INTEGER); vhdl_type integer(VHDL_TYPE_INTEGER);
vhdl_expr *r_cast = rhs->cast(&integer); vhdl_expr *r_cast = rhs->cast(&integer);
@ -311,7 +311,7 @@ static int draw_mux_lpm(vhdl_arch *arch, ivl_lpm_t lpm)
} }
vhdl_scope *scope = arch->get_scope(); vhdl_scope *scope = arch->get_scope();
vhdl_expr *s0 = readable_ref(scope, ivl_lpm_data(lpm, 0)); vhdl_expr *s0 = readable_ref(scope, ivl_lpm_data(lpm, 0));
vhdl_expr *s1 = readable_ref(scope, ivl_lpm_data(lpm, 1)); vhdl_expr *s1 = readable_ref(scope, ivl_lpm_data(lpm, 1));
@ -319,7 +319,7 @@ static int draw_mux_lpm(vhdl_arch *arch, ivl_lpm_t lpm)
vhdl_expr *b1 = new vhdl_const_bit('1'); vhdl_expr *b1 = new vhdl_const_bit('1');
vhdl_expr *t1 = vhdl_expr *t1 =
new vhdl_binop_expr(sel, VHDL_BINOP_EQ, b1, vhdl_type::boolean()); new vhdl_binop_expr(sel, VHDL_BINOP_EQ, b1, vhdl_type::boolean());
vhdl_var_ref *out = nexus_to_var_ref(scope, ivl_lpm_q(lpm)); vhdl_var_ref *out = nexus_to_var_ref(scope, ivl_lpm_q(lpm));
// Make sure s0 and s1 have the same type as the output // Make sure s0 and s1 have the same type as the output
@ -337,11 +337,11 @@ int draw_lpm(vhdl_arch *arch, ivl_lpm_t lpm)
{ {
if (ivl_lpm_type(lpm) == IVL_LPM_MUX) if (ivl_lpm_type(lpm) == IVL_LPM_MUX)
return draw_mux_lpm(arch, lpm); return draw_mux_lpm(arch, lpm);
vhdl_expr *f = lpm_to_expr(arch->get_scope(), lpm); vhdl_expr *f = lpm_to_expr(arch->get_scope(), lpm);
if (NULL == f) if (NULL == f)
return 1; return 1;
vhdl_var_ref *out = nexus_to_var_ref(arch->get_scope(), ivl_lpm_q(lpm)); vhdl_var_ref *out = nexus_to_var_ref(arch->get_scope(), ivl_lpm_q(lpm));
if (ivl_lpm_type(lpm) == IVL_LPM_PART_PV) { if (ivl_lpm_type(lpm) == IVL_LPM_PART_PV) {
vhdl_expr *off = part_select_base(arch->get_scope(), lpm); vhdl_expr *off = part_select_base(arch->get_scope(), lpm);
@ -357,16 +357,16 @@ int draw_lpm(vhdl_arch *arch, ivl_lpm_t lpm)
bool bool_to_logic = bool bool_to_logic =
out->get_type()->get_name() == VHDL_TYPE_STD_LOGIC out->get_type()->get_name() == VHDL_TYPE_STD_LOGIC
&& f->get_type()->get_name() == VHDL_TYPE_BOOLEAN; && f->get_type()->get_name() == VHDL_TYPE_BOOLEAN;
if (bool_to_logic) { if (bool_to_logic) {
vhdl_cassign_stmt* s = vhdl_cassign_stmt* s =
new vhdl_cassign_stmt(out, new vhdl_const_bit('0')); new vhdl_cassign_stmt(out, new vhdl_const_bit('0'));
s->add_condition(new vhdl_const_bit('1'), f); s->add_condition(new vhdl_const_bit('1'), f);
arch->add_stmt(s); arch->add_stmt(s);
} }
else else
arch->add_stmt(new vhdl_cassign_stmt(out, f->cast(out->get_type()))); arch->add_stmt(new vhdl_cassign_stmt(out, f->cast(out->get_type())));
return 0; return 0;
} }

View File

@ -33,7 +33,7 @@
static int generate_vhdl_process(vhdl_entity *ent, ivl_process_t proc) static int generate_vhdl_process(vhdl_entity *ent, ivl_process_t proc)
{ {
set_active_entity(ent); set_active_entity(ent);
// Create a new process and store it in the entity's // Create a new process and store it in the entity's
// architecture. This needs to be done first or the // architecture. This needs to be done first or the
// parent link won't be valid (and draw_stmt needs this // parent link won't be valid (and draw_stmt needs this
@ -45,7 +45,7 @@ static int generate_vhdl_process(vhdl_entity *ent, ivl_process_t proc)
// into the declarations // into the declarations
vhdl_proc->get_scope()->set_initializing vhdl_proc->get_scope()->set_initializing
(ivl_process_type(proc) == IVL_PR_INITIAL); (ivl_process_type(proc) == IVL_PR_INITIAL);
ivl_statement_t stmt = ivl_process_stmt(proc); ivl_statement_t stmt = ivl_process_stmt(proc);
int rc = draw_stmt(vhdl_proc, vhdl_proc->get_container(), stmt); int rc = draw_stmt(vhdl_proc, vhdl_proc->get_container(), stmt);
if (rc != 0) if (rc != 0)
@ -57,14 +57,17 @@ static int generate_vhdl_process(vhdl_entity *ent, ivl_process_t proc)
// However, if no statements were added to the container // However, if no statements were added to the container
// by draw_stmt, don't bother adding a wait as `emit' // by draw_stmt, don't bother adding a wait as `emit'
// will optimise the process out of the output // will optimise the process out of the output
bool is_initial = ivl_process_type(proc) == IVL_PR_INITIAL; if (ivl_process_type(proc) == IVL_PR_INITIAL) {
bool is_empty = vhdl_proc->get_container()->empty(); // Get rid of any useless `wait for 0 ns's at the end of the process
prune_wait_for_0(vhdl_proc->get_container());
if (is_initial && !is_empty) {
vhdl_wait_stmt *wait = new vhdl_wait_stmt(); // The above pruning might have removed all logic from the process
vhdl_proc->get_container()->add_stmt(wait); if (!vhdl_proc->get_container()->empty()) {
vhdl_wait_stmt *wait = new vhdl_wait_stmt();
vhdl_proc->get_container()->add_stmt(wait);
}
} }
// Add a comment indicating where it came from // Add a comment indicating where it came from
ivl_scope_t scope = ivl_process_scope(proc); ivl_scope_t scope = ivl_process_scope(proc);
const char *type = ivl_process_type(proc) == IVL_PR_INITIAL const char *type = ivl_process_type(proc) == IVL_PR_INITIAL
@ -87,21 +90,21 @@ extern "C" int draw_process(ivl_process_t proc, void *cd)
if (!is_default_scope_instance(scope)) if (!is_default_scope_instance(scope))
return 0; // Ignore this process at it's not in a scope that return 0; // Ignore this process at it's not in a scope that
// we're using to generate code // we're using to generate code
debug_msg("Translating process in scope type %s (%s:%d)", debug_msg("Translating process in scope type %s (%s:%d)",
ivl_scope_tname(scope), ivl_process_file(proc), ivl_scope_tname(scope), ivl_process_file(proc),
ivl_process_lineno(proc)); ivl_process_lineno(proc));
// Skip over any generate and begin scopes until we find // Skip over any generate and begin scopes until we find
// the module that contains them - this is where we will // the module that contains them - this is where we will
// generate the process // generate the process
while (ivl_scope_type(scope) == IVL_SCT_GENERATE while (ivl_scope_type(scope) == IVL_SCT_GENERATE
|| ivl_scope_type(scope) == IVL_SCT_BEGIN) || ivl_scope_type(scope) == IVL_SCT_BEGIN)
scope = ivl_scope_parent(scope); scope = ivl_scope_parent(scope);
assert(ivl_scope_type(scope) == IVL_SCT_MODULE); assert(ivl_scope_type(scope) == IVL_SCT_MODULE);
vhdl_entity *ent = find_entity(scope); vhdl_entity *ent = find_entity(scope);
assert(ent != NULL); assert(ent != NULL);
return generate_vhdl_process(ent, proc); return generate_vhdl_process(ent, proc);
} }

View File

@ -42,7 +42,7 @@ struct scope_nexus_t {
string tmpname; // A new temporary signal string tmpname; // A new temporary signal
list<ivl_signal_t> connect; // Other signals to wire together list<ivl_signal_t> connect; // Other signals to wire together
}; };
/* /*
* This structure is stored in the private part of each nexus. * This structure is stored in the private part of each nexus.
* It stores a scope_nexus_t for each VHDL scope which is * It stores a scope_nexus_t for each VHDL scope which is
@ -76,11 +76,11 @@ static scope_nexus_t *visible_nexus(nexus_private_t *priv, vhdl_scope *scope)
*/ */
static void link_scope_to_nexus_signal(nexus_private_t *priv, vhdl_scope *scope, static void link_scope_to_nexus_signal(nexus_private_t *priv, vhdl_scope *scope,
ivl_signal_t sig, unsigned pin) ivl_signal_t sig, unsigned pin)
{ {
scope_nexus_t *sn; scope_nexus_t *sn;
if ((sn = visible_nexus(priv, scope))) { if ((sn = visible_nexus(priv, scope))) {
assert(sn->tmpname == ""); assert(sn->tmpname == "");
// Remember to connect this signal up later // Remember to connect this signal up later
// If one of the signals is a input, make sure the input is not being driven // If one of the signals is a input, make sure the input is not being driven
if (ivl_signal_port(sn->sig) == IVL_SIP_INPUT) if (ivl_signal_port(sn->sig) == IVL_SIP_INPUT)
@ -126,16 +126,16 @@ static ivl_signal_type_t signal_type_of_nexus(ivl_nexus_t nex, int &width)
{ {
ivl_signal_type_t out = IVL_SIT_TRI; ivl_signal_type_t out = IVL_SIT_TRI;
width = 0; width = 0;
for (unsigned idx = 0; idx < ivl_nexus_ptrs(nex); idx += 1) { for (unsigned idx = 0; idx < ivl_nexus_ptrs(nex); idx += 1) {
ivl_signal_type_t stype; ivl_signal_type_t stype;
ivl_nexus_ptr_t ptr = ivl_nexus_ptr(nex, idx); ivl_nexus_ptr_t ptr = ivl_nexus_ptr(nex, idx);
ivl_signal_t sig = ivl_nexus_ptr_sig(ptr); ivl_signal_t sig = ivl_nexus_ptr_sig(ptr);
if (sig == 0) if (sig == 0)
continue; continue;
width = ivl_signal_width(sig); width = ivl_signal_width(sig);
stype = ivl_signal_type(sig); stype = ivl_signal_type(sig);
if (stype == IVL_SIT_TRI) if (stype == IVL_SIT_TRI)
continue; continue;
@ -143,7 +143,7 @@ static ivl_signal_type_t signal_type_of_nexus(ivl_nexus_t nex, int &width)
continue; continue;
out = stype; out = stype;
} }
return out; return out;
} }
@ -151,11 +151,11 @@ static ivl_signal_type_t signal_type_of_nexus(ivl_nexus_t nex, int &width)
* Generates VHDL code to fully represent a nexus. * Generates VHDL code to fully represent a nexus.
*/ */
void draw_nexus(ivl_nexus_t nexus) void draw_nexus(ivl_nexus_t nexus)
{ {
nexus_private_t *priv = new nexus_private_t; nexus_private_t *priv = new nexus_private_t;
int nexus_signal_width = -1; int nexus_signal_width = -1;
priv->const_driver = NULL; priv->const_driver = NULL;
int nptrs = ivl_nexus_ptrs(nexus); int nptrs = ivl_nexus_ptrs(nexus);
// Number of drivers for this nexus // Number of drivers for this nexus
@ -164,9 +164,9 @@ void draw_nexus(ivl_nexus_t nexus)
// First pass through connect all the signals up // First pass through connect all the signals up
for (int i = 0; i < nptrs; i++) { for (int i = 0; i < nptrs; i++) {
ivl_nexus_ptr_t nexus_ptr = ivl_nexus_ptr(nexus, i); ivl_nexus_ptr_t nexus_ptr = ivl_nexus_ptr(nexus, i);
ivl_signal_t sig; ivl_signal_t sig;
if ((sig = ivl_nexus_ptr_sig(nexus_ptr))) { if ((sig = ivl_nexus_ptr_sig(nexus_ptr))) {
vhdl_scope *scope = find_scope_for_signal(sig); vhdl_scope *scope = find_scope_for_signal(sig);
if (scope) { if (scope) {
unsigned pin = ivl_nexus_ptr_pin(nexus_ptr); unsigned pin = ivl_nexus_ptr_pin(nexus_ptr);
@ -181,7 +181,7 @@ void draw_nexus(ivl_nexus_t nexus)
// inputs and outputs // inputs and outputs
for (int i = 0; i < nptrs; i++) { for (int i = 0; i < nptrs; i++) {
ivl_nexus_ptr_t nexus_ptr = ivl_nexus_ptr(nexus, i); ivl_nexus_ptr_t nexus_ptr = ivl_nexus_ptr(nexus, i);
ivl_net_logic_t log; ivl_net_logic_t log;
ivl_lpm_t lpm; ivl_lpm_t lpm;
ivl_net_const_t con; ivl_net_const_t con;
@ -189,10 +189,10 @@ void draw_nexus(ivl_nexus_t nexus)
ivl_scope_t log_scope = ivl_logic_scope(log); ivl_scope_t log_scope = ivl_logic_scope(log);
if (!is_default_scope_instance(log_scope)) if (!is_default_scope_instance(log_scope))
continue; continue;
vhdl_entity *ent = find_entity(log_scope); vhdl_entity *ent = find_entity(log_scope);
assert(ent); assert(ent);
vhdl_scope *vhdl_scope = ent->get_arch()->get_scope(); vhdl_scope *vhdl_scope = ent->get_arch()->get_scope();
if (visible_nexus(priv, vhdl_scope)) { if (visible_nexus(priv, vhdl_scope)) {
// Already seen this signal in vhdl_scope // Already seen this signal in vhdl_scope
@ -201,7 +201,7 @@ void draw_nexus(ivl_nexus_t nexus)
// Create a temporary signal to connect it to the nexus // Create a temporary signal to connect it to the nexus
vhdl_type *type = vhdl_type *type =
vhdl_type::type_for(ivl_logic_width(log), false); vhdl_type::type_for(ivl_logic_width(log), false);
ostringstream ss; ostringstream ss;
ss << "LO" << ivl_logic_basename(log); ss << "LO" << ivl_logic_basename(log);
vhdl_scope->add_decl(new vhdl_signal_decl(ss.str().c_str(), type)); vhdl_scope->add_decl(new vhdl_signal_decl(ss.str().c_str(), type));
@ -218,7 +218,7 @@ void draw_nexus(ivl_nexus_t nexus)
ivl_scope_t lpm_scope = ivl_lpm_scope(lpm); ivl_scope_t lpm_scope = ivl_lpm_scope(lpm);
vhdl_entity *ent = find_entity(lpm_scope); vhdl_entity *ent = find_entity(lpm_scope);
assert(ent); assert(ent);
vhdl_scope *vhdl_scope = ent->get_arch()->get_scope(); vhdl_scope *vhdl_scope = ent->get_arch()->get_scope();
if (visible_nexus(priv, vhdl_scope)) { if (visible_nexus(priv, vhdl_scope)) {
// Already seen this signal in vhdl_scope // Already seen this signal in vhdl_scope
@ -235,7 +235,7 @@ void draw_nexus(ivl_nexus_t nexus)
lpm_temp_width = nexus_signal_width; lpm_temp_width = nexus_signal_width;
else else
lpm_temp_width = ivl_lpm_width(lpm); lpm_temp_width = ivl_lpm_width(lpm);
vhdl_type *type = vhdl_type::type_for(lpm_temp_width, vhdl_type *type = vhdl_type::type_for(lpm_temp_width,
ivl_lpm_signed(lpm) != 0); ivl_lpm_signed(lpm) != 0);
ostringstream ss; ostringstream ss;
@ -243,7 +243,7 @@ void draw_nexus(ivl_nexus_t nexus)
if (!vhdl_scope->have_declared(ss.str())) if (!vhdl_scope->have_declared(ss.str()))
vhdl_scope->add_decl(new vhdl_signal_decl(ss.str().c_str(), type)); vhdl_scope->add_decl(new vhdl_signal_decl(ss.str().c_str(), type));
link_scope_to_nexus_tmp(priv, vhdl_scope, ss.str()); link_scope_to_nexus_tmp(priv, vhdl_scope, ss.str());
} }
@ -274,7 +274,7 @@ void draw_nexus(ivl_nexus_t nexus)
if (ndrivers == 0) { if (ndrivers == 0) {
char def = 0; char def = 0;
int width; int width;
switch (signal_type_of_nexus(nexus, width)) { switch (signal_type_of_nexus(nexus, width)) {
case IVL_SIT_TRI: case IVL_SIT_TRI:
case IVL_SIT_UWIRE: case IVL_SIT_UWIRE:
@ -305,7 +305,7 @@ void draw_nexus(ivl_nexus_t nexus)
priv->const_driver = new vhdl_const_bit(def); priv->const_driver = new vhdl_const_bit(def);
} }
} }
// Save the private data in the nexus // Save the private data in the nexus
ivl_nexus_set_private(nexus, priv); ivl_nexus_set_private(nexus, priv);
} }
@ -316,10 +316,10 @@ void draw_nexus(ivl_nexus_t nexus)
*/ */
static void seen_nexus(ivl_nexus_t nexus) static void seen_nexus(ivl_nexus_t nexus)
{ {
if (ivl_nexus_get_private(nexus) == NULL) if (ivl_nexus_get_private(nexus) == NULL)
draw_nexus(nexus); draw_nexus(nexus);
} }
/* /*
* Translate a nexus to a variable reference. Given a nexus and a * Translate a nexus to a variable reference. Given a nexus and a
* scope, this function returns a reference to a signal that is * scope, this function returns a reference to a signal that is
@ -332,18 +332,18 @@ static void seen_nexus(ivl_nexus_t nexus)
vhdl_var_ref *nexus_to_var_ref(vhdl_scope *scope, ivl_nexus_t nexus) vhdl_var_ref *nexus_to_var_ref(vhdl_scope *scope, ivl_nexus_t nexus)
{ {
seen_nexus(nexus); seen_nexus(nexus);
nexus_private_t *priv = nexus_private_t *priv =
static_cast<nexus_private_t*>(ivl_nexus_get_private(nexus)); static_cast<nexus_private_t*>(ivl_nexus_get_private(nexus));
unsigned pin; unsigned pin;
string renamed(visible_nexus_signal_name(priv, scope, &pin)); string renamed(visible_nexus_signal_name(priv, scope, &pin));
vhdl_decl *decl = scope->get_decl(renamed); vhdl_decl *decl = scope->get_decl(renamed);
assert(decl); assert(decl);
vhdl_type *type = new vhdl_type(*(decl->get_type())); vhdl_type *type = new vhdl_type(*(decl->get_type()));
vhdl_var_ref *ref = new vhdl_var_ref(renamed.c_str(), type); vhdl_var_ref *ref = new vhdl_var_ref(renamed.c_str(), type);
if (decl->get_type()->get_name() == VHDL_TYPE_ARRAY) if (decl->get_type()->get_name() == VHDL_TYPE_ARRAY)
ref->set_slice(new vhdl_const_int(pin), 0); ref->set_slice(new vhdl_const_int(pin), 0);
@ -355,7 +355,7 @@ vhdl_var_ref *nexus_to_var_ref(vhdl_scope *scope, ivl_nexus_t nexus)
vhdl_var_ref* readable_ref(vhdl_scope* scope, ivl_nexus_t nex) vhdl_var_ref* readable_ref(vhdl_scope* scope, ivl_nexus_t nex)
{ {
vhdl_var_ref* ref = nexus_to_var_ref(scope, nex); vhdl_var_ref* ref = nexus_to_var_ref(scope, nex);
vhdl_decl* decl = scope->get_decl(ref->get_name()); vhdl_decl* decl = scope->get_decl(ref->get_name());
decl->ensure_readable(); decl->ensure_readable();
@ -369,10 +369,10 @@ vhdl_var_ref* readable_ref(vhdl_scope* scope, ivl_nexus_t nex)
static void declare_logic(vhdl_arch *arch, ivl_scope_t scope) static void declare_logic(vhdl_arch *arch, ivl_scope_t scope)
{ {
debug_msg("Declaring logic in scope type %s", ivl_scope_tname(scope)); debug_msg("Declaring logic in scope type %s", ivl_scope_tname(scope));
int nlogs = ivl_scope_logs(scope); int nlogs = ivl_scope_logs(scope);
for (int i = 0; i < nlogs; i++) for (int i = 0; i < nlogs; i++)
draw_logic(arch, ivl_scope_log(scope, i)); draw_logic(arch, ivl_scope_log(scope, i));
} }
// Replace consecutive underscores with a single underscore // Replace consecutive underscores with a single underscore
@ -422,7 +422,7 @@ static string valid_entity_name(const string& module_name)
name = "module" + name; name = "module" + name;
if (*name.rbegin() == '_') if (*name.rbegin() == '_')
name += "module"; name += "module";
if (is_vhdl_reserved_word(name)) if (is_vhdl_reserved_word(name))
name += "_module"; name += "_module";
@ -434,7 +434,7 @@ static string valid_entity_name(const string& module_name)
ss.str(""); ss.str("");
ss << name << i++; ss << name << i++;
} }
return ss.str(); return ss.str();
} }
@ -445,7 +445,7 @@ string make_safe_name(ivl_signal_t sig)
if (ivl_signal_local(sig)) if (ivl_signal_local(sig))
base = "tmp" + base; base = "tmp" + base;
if (base[0] == '_') if (base[0] == '_')
base = "sig" + base; base = "sig" + base;
@ -454,14 +454,14 @@ string make_safe_name(ivl_signal_t sig)
// Can't have two consecutive underscores // Can't have two consecutive underscores
replace_consecutive_underscores(base); replace_consecutive_underscores(base);
// A signal name may not be the same as a component name // A signal name may not be the same as a component name
if (find_entity(base) != NULL) if (find_entity(base) != NULL)
base += "_sig"; base += "_sig";
if (is_vhdl_reserved_word(base)) if (is_vhdl_reserved_word(base))
base += "_sig"; base += "_sig";
return base; return base;
} }
@ -478,7 +478,7 @@ static void avoid_name_collision(string& name, vhdl_scope* scope)
ss.str(""); ss.str("");
ss << name << i++; ss << name << i++;
} while (scope->name_collides(ss.str())); } while (scope->name_collides(ss.str()));
name = ss.str(); name = ss.str();
} }
} }
@ -495,24 +495,24 @@ static string genvar_unique_suffix(ivl_scope_t scope)
for (unsigned i = 0; i < ivl_scope_params(scope); i++) { for (unsigned i = 0; i < ivl_scope_params(scope); i++) {
ivl_parameter_t param = ivl_scope_param(scope, i); ivl_parameter_t param = ivl_scope_param(scope, i);
ivl_expr_t e = ivl_parameter_expr(param); ivl_expr_t e = ivl_parameter_expr(param);
if (ivl_expr_type(e) == IVL_EX_NUMBER) { if (ivl_expr_type(e) == IVL_EX_NUMBER) {
vhdl_expr* value = translate_expr(e); vhdl_expr* value = translate_expr(e);
assert(value); assert(value);
value = value->cast(vhdl_type::integer()); value = value->cast(vhdl_type::integer());
suffix << "_" << ivl_parameter_basename(param); suffix << "_" << ivl_parameter_basename(param);
value->emit(suffix, 0); value->emit(suffix, 0);
delete value; delete value;
} }
else { else {
error("Only numeric genvars supported at the moment"); error("Only numeric genvars supported at the moment");
return "_ERROR"; // Never used return "_ERROR"; // Never used
} }
} }
scope = ivl_scope_parent(scope); scope = ivl_scope_parent(scope);
} }
@ -528,33 +528,33 @@ static void declare_one_signal(vhdl_entity *ent, ivl_signal_t sig,
string name(make_safe_name(sig)); string name(make_safe_name(sig));
name += genvar_unique_suffix(scope); name += genvar_unique_suffix(scope);
avoid_name_collision(name, ent->get_arch()->get_scope()); avoid_name_collision(name, ent->get_arch()->get_scope());
rename_signal(sig, name); rename_signal(sig, name);
vhdl_type *sig_type; vhdl_type *sig_type;
unsigned dimensions = ivl_signal_dimensions(sig); unsigned dimensions = ivl_signal_dimensions(sig);
if (dimensions > 0) { if (dimensions > 0) {
// Arrays are implemented by generating a separate type // Arrays are implemented by generating a separate type
// declaration for each array, and then declaring a // declaration for each array, and then declaring a
// signal of that type // signal of that type
if (dimensions > 1) { if (dimensions > 1) {
error("> 1 dimension arrays not implemented yet"); error("> 1 dimension arrays not implemented yet");
return; return;
} }
string type_name = name + "_Type"; string type_name = name + "_Type";
vhdl_type *base_type = vhdl_type *base_type =
vhdl_type::type_for(ivl_signal_width(sig), ivl_signal_signed(sig) != 0); vhdl_type::type_for(ivl_signal_width(sig), ivl_signal_signed(sig) != 0);
int lsb = ivl_signal_array_base(sig); int lsb = ivl_signal_array_base(sig);
int msb = lsb + ivl_signal_array_count(sig) - 1; int msb = lsb + ivl_signal_array_count(sig) - 1;
vhdl_type *array_type = vhdl_type *array_type =
vhdl_type::array_of(base_type, type_name, msb, lsb); vhdl_type::array_of(base_type, type_name, msb, lsb);
vhdl_decl *array_decl = new vhdl_type_decl(type_name.c_str(), array_type); vhdl_decl *array_decl = new vhdl_type_decl(type_name.c_str(), array_type);
ent->get_arch()->get_scope()->add_decl(array_decl); ent->get_arch()->get_scope()->add_decl(array_decl);
sig_type = new vhdl_type(*array_type); sig_type = new vhdl_type(*array_type);
} }
else { else {
@ -562,15 +562,15 @@ static void declare_one_signal(vhdl_entity *ent, ivl_signal_t sig,
ivl_signal_signed(sig) != 0, ivl_signal_signed(sig) != 0,
0, ivl_signal_type(sig) == IVL_SIT_UWIRE); 0, ivl_signal_type(sig) == IVL_SIT_UWIRE);
} }
ivl_signal_port_t mode = ivl_signal_port(sig); ivl_signal_port_t mode = ivl_signal_port(sig);
switch (mode) { switch (mode) {
case IVL_SIP_NONE: case IVL_SIP_NONE:
{ {
vhdl_decl *decl = new vhdl_signal_decl(name.c_str(), sig_type); vhdl_decl *decl = new vhdl_signal_decl(name.c_str(), sig_type);
ostringstream ss; ostringstream ss;
if (ivl_signal_local(sig)) { if (ivl_signal_local(sig)) {
ss << "Temporary created at " << ivl_signal_file(sig) << ":" ss << "Temporary created at " << ivl_signal_file(sig) << ":"
@ -580,7 +580,7 @@ static void declare_one_signal(vhdl_entity *ent, ivl_signal_t sig,
<< ivl_signal_lineno(sig); << ivl_signal_lineno(sig);
} }
decl->set_comment(ss.str().c_str()); decl->set_comment(ss.str().c_str());
ent->get_arch()->get_scope()->add_decl(decl); ent->get_arch()->get_scope()->add_decl(decl);
} }
break; break;
@ -591,10 +591,10 @@ static void declare_one_signal(vhdl_entity *ent, ivl_signal_t sig,
case IVL_SIP_OUTPUT: case IVL_SIP_OUTPUT:
{ {
vhdl_port_decl *decl = vhdl_port_decl *decl =
new vhdl_port_decl(name.c_str(), sig_type, VHDL_PORT_OUT); new vhdl_port_decl(name.c_str(), sig_type, VHDL_PORT_OUT);
ent->get_scope()->add_decl(decl); ent->get_scope()->add_decl(decl);
} }
if (ivl_signal_type(sig) == IVL_SIT_REG) { if (ivl_signal_type(sig) == IVL_SIT_REG) {
// A registered output // A registered output
// In Verilog the output and reg can have the // In Verilog the output and reg can have the
@ -604,11 +604,11 @@ static void declare_one_signal(vhdl_entity *ent, ivl_signal_t sig,
std::string newname(name); std::string newname(name);
newname += "_Reg"; newname += "_Reg";
rename_signal(sig, newname.c_str()); rename_signal(sig, newname.c_str());
vhdl_type *reg_type = new vhdl_type(*sig_type); vhdl_type *reg_type = new vhdl_type(*sig_type);
ent->get_arch()->get_scope()->add_decl ent->get_arch()->get_scope()->add_decl
(new vhdl_signal_decl(newname.c_str(), reg_type)); (new vhdl_signal_decl(newname.c_str(), reg_type));
// Create a concurrent assignment statement to // Create a concurrent assignment statement to
// connect the register to the output // connect the register to the output
ent->get_arch()->add_stmt ent->get_arch()->add_stmt
@ -633,17 +633,17 @@ static void declare_one_signal(vhdl_entity *ent, ivl_signal_t sig,
static void declare_signals(vhdl_entity *ent, ivl_scope_t scope) static void declare_signals(vhdl_entity *ent, ivl_scope_t scope)
{ {
debug_msg("Declaring signals in scope type %s", ivl_scope_tname(scope)); debug_msg("Declaring signals in scope type %s", ivl_scope_tname(scope));
int nsigs = ivl_scope_sigs(scope); int nsigs = ivl_scope_sigs(scope);
for (int i = 0; i < nsigs; i++) { for (int i = 0; i < nsigs; i++) {
ivl_signal_t sig = ivl_scope_sig(scope, i); ivl_signal_t sig = ivl_scope_sig(scope, i);
if (ivl_signal_port(sig) != IVL_SIP_NONE) if (ivl_signal_port(sig) != IVL_SIP_NONE)
declare_one_signal(ent, sig, scope); declare_one_signal(ent, sig, scope);
} }
for (int i = 0; i < nsigs; i++) { for (int i = 0; i < nsigs; i++) {
ivl_signal_t sig = ivl_scope_sig(scope, i); ivl_signal_t sig = ivl_scope_sig(scope, i);
if (ivl_signal_port(sig) == IVL_SIP_NONE) if (ivl_signal_port(sig) == IVL_SIP_NONE)
declare_one_signal(ent, sig, scope); declare_one_signal(ent, sig, scope);
@ -669,7 +669,7 @@ static void declare_lpm(vhdl_arch *arch, ivl_scope_t scope)
*/ */
static void map_signal(ivl_signal_t to, vhdl_entity *parent, static void map_signal(ivl_signal_t to, vhdl_entity *parent,
vhdl_comp_inst *inst) vhdl_comp_inst *inst)
{ {
// TODO: Work for multiple words // TODO: Work for multiple words
ivl_nexus_t nexus = ivl_signal_nex(to, 0); ivl_nexus_t nexus = ivl_signal_nex(to, 0);
seen_nexus(nexus); seen_nexus(nexus);
@ -699,14 +699,14 @@ static void map_signal(ivl_signal_t to, vhdl_entity *parent,
&& !arch_scope->have_declared(name + "_Readable")) { && !arch_scope->have_declared(name + "_Readable")) {
vhdl_decl* tmp_decl = vhdl_decl* tmp_decl =
new vhdl_signal_decl(name + "_Readable", ref->get_type()); new vhdl_signal_decl(name + "_Readable", ref->get_type());
// Add a comment to explain what this is for // Add a comment to explain what this is for
tmp_decl->set_comment("Needed to connect outputs"); tmp_decl->set_comment("Needed to connect outputs");
arch_scope->add_decl(tmp_decl); arch_scope->add_decl(tmp_decl);
parent->get_arch()->add_stmt parent->get_arch()->add_stmt
(new vhdl_cassign_stmt(from_decl->make_ref(), tmp_decl->make_ref())); (new vhdl_cassign_stmt(from_decl->make_ref(), tmp_decl->make_ref()));
map_to = tmp_decl->make_ref(); map_to = tmp_decl->make_ref();
} }
else else
@ -719,7 +719,7 @@ static void map_signal(ivl_signal_t to, vhdl_entity *parent,
else { else {
// This nexus isn't attached to anything in the parent // This nexus isn't attached to anything in the parent
return; return;
} }
inst->map_port(name, map_to); inst->map_port(name, map_to);
} }
@ -734,7 +734,7 @@ static void port_map(ivl_scope_t scope, vhdl_entity *parent,
int nsigs = ivl_scope_sigs(scope); int nsigs = ivl_scope_sigs(scope);
for (int i = 0; i < nsigs; i++) { for (int i = 0; i < nsigs; i++) {
ivl_signal_t sig = ivl_scope_sig(scope, i); ivl_signal_t sig = ivl_scope_sig(scope, i);
ivl_signal_port_t mode = ivl_signal_port(sig); ivl_signal_port_t mode = ivl_signal_port(sig);
switch (mode) { switch (mode) {
case IVL_SIP_NONE: case IVL_SIP_NONE:
@ -744,10 +744,10 @@ static void port_map(ivl_scope_t scope, vhdl_entity *parent,
case IVL_SIP_OUTPUT: case IVL_SIP_OUTPUT:
case IVL_SIP_INOUT: case IVL_SIP_INOUT:
map_signal(sig, parent, inst); map_signal(sig, parent, inst);
break; break;
default: default:
assert(false); assert(false);
} }
} }
} }
@ -788,9 +788,9 @@ static int draw_function(ivl_scope_t scope, ivl_scope_t parent)
vhdl_type *sigtype = vhdl_type *sigtype =
vhdl_type::type_for(ivl_signal_width(sig), vhdl_type::type_for(ivl_signal_width(sig),
ivl_signal_signed(sig) != 0); ivl_signal_signed(sig) != 0);
string signame(make_safe_name(sig)); string signame(make_safe_name(sig));
switch (ivl_signal_port(sig)) { switch (ivl_signal_port(sig)) {
case IVL_SIP_INPUT: case IVL_SIP_INPUT:
func->add_param(new vhdl_param_decl(signame.c_str(), sigtype)); func->add_param(new vhdl_param_decl(signame.c_str(), sigtype));
@ -807,30 +807,30 @@ static int draw_function(ivl_scope_t scope, ivl_scope_t parent)
// Only expecting inputs and outputs // Only expecting inputs and outputs
assert(false); assert(false);
} }
remember_signal(sig, func->get_scope()); remember_signal(sig, func->get_scope());
rename_signal(sig, signame); rename_signal(sig, signame);
} }
int nsigs = ivl_scope_sigs(scope); int nsigs = ivl_scope_sigs(scope);
for (int i = 0; i < nsigs; i++) { for (int i = 0; i < nsigs; i++) {
ivl_signal_t sig = ivl_scope_sig(scope, i); ivl_signal_t sig = ivl_scope_sig(scope, i);
if (ivl_signal_port(sig) == IVL_SIP_NONE) { if (ivl_signal_port(sig) == IVL_SIP_NONE) {
vhdl_type *sigtype = vhdl_type *sigtype =
vhdl_type::type_for( vhdl_type::type_for(
ivl_signal_width(sig), ivl_signal_width(sig),
ivl_signal_signed(sig) != 0); ivl_signal_signed(sig) != 0);
string signame(make_safe_name(sig)); string signame(make_safe_name(sig));
func->get_scope()->add_decl( func->get_scope()->add_decl(
new vhdl_var_decl(signame, sigtype)); new vhdl_var_decl(signame, sigtype));
remember_signal(sig, func->get_scope()); remember_signal(sig, func->get_scope());
rename_signal(sig, signame); rename_signal(sig, signame);
} }
} }
// Non-blocking assignment not allowed in functions // Non-blocking assignment not allowed in functions
func->get_scope()->set_allow_signal_assignment(false); func->get_scope()->set_allow_signal_assignment(false);
@ -849,8 +849,8 @@ static int draw_function(ivl_scope_t scope, ivl_scope_t parent)
ss << "Generated from function " << funcname << " at " ss << "Generated from function " << funcname << " at "
<< ivl_scope_def_file(scope) << ":" << ivl_scope_def_lineno(scope); << ivl_scope_def_file(scope) << ":" << ivl_scope_def_lineno(scope);
func->set_comment(ss.str().c_str()); func->set_comment(ss.str().c_str());
ent->get_arch()->get_scope()->add_decl(func); ent->get_arch()->get_scope()->add_decl(func);
return 0; return 0;
} }
@ -867,14 +867,14 @@ static int draw_task(ivl_scope_t scope, ivl_scope_t parent)
assert(ent); assert(ent);
const char *taskname = ivl_scope_tname(scope); const char *taskname = ivl_scope_tname(scope);
int nsigs = ivl_scope_sigs(scope); int nsigs = ivl_scope_sigs(scope);
for (int i = 0; i < nsigs; i++) { for (int i = 0; i < nsigs; i++) {
ivl_signal_t sig = ivl_scope_sig(scope, i); ivl_signal_t sig = ivl_scope_sig(scope, i);
vhdl_type *sigtype = vhdl_type *sigtype =
vhdl_type::type_for(ivl_signal_width(sig), vhdl_type::type_for(ivl_signal_width(sig),
ivl_signal_signed(sig) != 0); ivl_signal_signed(sig) != 0);
string signame(make_safe_name(sig)); string signame(make_safe_name(sig));
// Check this signal isn't declared in the outer scope // Check this signal isn't declared in the outer scope
@ -889,13 +889,13 @@ static int draw_task(ivl_scope_t scope, ivl_scope_t parent)
ss << "Declared at " << ivl_signal_file(sig) << ":" ss << "Declared at " << ivl_signal_file(sig) << ":"
<< ivl_signal_lineno(sig) << " (in task " << taskname << ")"; << ivl_signal_lineno(sig) << " (in task " << taskname << ")";
decl->set_comment(ss.str().c_str()); decl->set_comment(ss.str().c_str());
ent->get_arch()->get_scope()->add_decl(decl); ent->get_arch()->get_scope()->add_decl(decl);
remember_signal(sig, ent->get_arch()->get_scope()); remember_signal(sig, ent->get_arch()->get_scope());
rename_signal(sig, signame); rename_signal(sig, signame);
} }
return 0; return 0;
} }
@ -908,7 +908,7 @@ static void create_skeleton_entity_for(ivl_scope_t scope, int depth)
// The type name will become the entity name // The type name will become the entity name
const string tname = valid_entity_name(ivl_scope_tname(scope)); const string tname = valid_entity_name(ivl_scope_tname(scope));
// Verilog does not have the entity/architecture distinction // Verilog does not have the entity/architecture distinction
// so we always create a pair and associate the architecture // so we always create a pair and associate the architecture
// with the entity for convenience (this also means that we // with the entity for convenience (this also means that we
@ -926,29 +926,9 @@ static void create_skeleton_entity_for(ivl_scope_t scope, int depth)
<< " (" << ivl_scope_def_file(scope) << ":" << " (" << ivl_scope_def_file(scope) << ":"
<< ivl_scope_def_lineno(scope) << ")"; << ivl_scope_def_lineno(scope) << ")";
unsigned nparams = ivl_scope_params(scope);
for (unsigned i = 0; i < nparams; i++) {
ivl_parameter_t param = ivl_scope_param(scope, i);
ss << "\n " << ivl_parameter_basename(param) << " = ";
ivl_expr_t value = ivl_parameter_expr(param);
switch (ivl_expr_type(value)) {
case IVL_EX_STRING:
ss << "\"" << ivl_expr_string(value) << "\"";
break;
case IVL_EX_NUMBER:
ss << ivl_expr_uvalue(value);
break;
default:
assert(false);
}
}
arch->set_comment(ss.str()); arch->set_comment(ss.str());
ent->set_comment(ss.str()); ent->set_comment(ss.str());
remember_entity(ent, scope); remember_entity(ent, scope);
} }
@ -962,10 +942,10 @@ extern "C" int draw_skeleton_scope(ivl_scope_t scope, void *_unused)
if (seen_this_scope_type(scope)) if (seen_this_scope_type(scope))
return 0; // Already generated a skeleton for this scope type return 0; // Already generated a skeleton for this scope type
debug_msg("Initial visit to scope type %s at depth %d", debug_msg("Initial visit to scope type %s at depth %d",
ivl_scope_tname(scope), depth); ivl_scope_tname(scope), depth);
switch (ivl_scope_type(scope)) { switch (ivl_scope_type(scope)) {
case IVL_SCT_MODULE: case IVL_SCT_MODULE:
create_skeleton_entity_for(scope, depth); create_skeleton_entity_for(scope, depth);
@ -988,7 +968,7 @@ extern "C" int draw_all_signals(ivl_scope_t scope, void *_parent)
{ {
if (!is_default_scope_instance(scope)) if (!is_default_scope_instance(scope))
return 0; // Not interested in this instance return 0; // Not interested in this instance
if (ivl_scope_type(scope) == IVL_SCT_MODULE) { if (ivl_scope_type(scope) == IVL_SCT_MODULE) {
vhdl_entity *ent = find_entity(scope); vhdl_entity *ent = find_entity(scope);
assert(ent); assert(ent);
@ -1003,7 +983,7 @@ extern "C" int draw_all_signals(ivl_scope_t scope, void *_parent)
ivl_scope_t parent = ivl_scope_parent(scope); ivl_scope_t parent = ivl_scope_parent(scope);
while (ivl_scope_type(parent) == IVL_SCT_GENERATE) while (ivl_scope_type(parent) == IVL_SCT_GENERATE)
parent = ivl_scope_parent(scope); parent = ivl_scope_parent(scope);
vhdl_entity* ent = find_entity(parent); vhdl_entity* ent = find_entity(parent);
assert(ent); assert(ent);
@ -1020,7 +1000,7 @@ extern "C" int draw_functions(ivl_scope_t scope, void *_parent)
{ {
if (!is_default_scope_instance(scope)) if (!is_default_scope_instance(scope))
return 0; // Not interested in this instance return 0; // Not interested in this instance
ivl_scope_t parent = static_cast<ivl_scope_t>(_parent); ivl_scope_t parent = static_cast<ivl_scope_t>(_parent);
if (ivl_scope_type(scope) == IVL_SCT_FUNCTION) { if (ivl_scope_type(scope) == IVL_SCT_FUNCTION) {
if (draw_function(scope, parent) != 0) if (draw_function(scope, parent) != 0)
@ -1044,9 +1024,9 @@ extern "C" int draw_constant_drivers(ivl_scope_t scope, void *_parent)
{ {
if (!is_default_scope_instance(scope)) if (!is_default_scope_instance(scope))
return 0; // Not interested in this instance return 0; // Not interested in this instance
ivl_scope_children(scope, draw_constant_drivers, scope); ivl_scope_children(scope, draw_constant_drivers, scope);
if (ivl_scope_type(scope) == IVL_SCT_MODULE) { if (ivl_scope_type(scope) == IVL_SCT_MODULE) {
vhdl_entity *ent = find_entity(scope); vhdl_entity *ent = find_entity(scope);
assert(ent); assert(ent);
@ -1054,7 +1034,7 @@ extern "C" int draw_constant_drivers(ivl_scope_t scope, void *_parent)
int nsigs = ivl_scope_sigs(scope); int nsigs = ivl_scope_sigs(scope);
for (int i = 0; i < nsigs; i++) { for (int i = 0; i < nsigs; i++) {
ivl_signal_t sig = ivl_scope_sig(scope, i); ivl_signal_t sig = ivl_scope_sig(scope, i);
for (unsigned j = ivl_signal_array_base(sig); for (unsigned j = ivl_signal_array_base(sig);
j < ivl_signal_array_count(sig); j < ivl_signal_array_count(sig);
j++) { j++) {
@ -1062,7 +1042,7 @@ extern "C" int draw_constant_drivers(ivl_scope_t scope, void *_parent)
ivl_nexus_t nex = ivl_signal_nex(sig, j); ivl_nexus_t nex = ivl_signal_nex(sig, j);
if (!nex) continue; // skip virtual pins if (!nex) continue; // skip virtual pins
seen_nexus(nex); seen_nexus(nex);
nexus_private_t *priv = nexus_private_t *priv =
static_cast<nexus_private_t*>(ivl_nexus_get_private(nex)); static_cast<nexus_private_t*>(ivl_nexus_get_private(nex));
assert(priv); assert(priv);
@ -1072,9 +1052,9 @@ extern "C" int draw_constant_drivers(ivl_scope_t scope, void *_parent)
if (priv->const_driver if (priv->const_driver
&& ivl_signal_port(sig) != IVL_SIP_INPUT) { // Don't drive inputs && ivl_signal_port(sig) != IVL_SIP_INPUT) { // Don't drive inputs
assert(j == 0); // TODO: Make work for more words assert(j == 0); // TODO: Make work for more words
vhdl_var_ref *ref = nexus_to_var_ref(arch_scope, nex); vhdl_var_ref *ref = nexus_to_var_ref(arch_scope, nex);
ent->get_arch()->add_stmt ent->get_arch()->add_stmt
(new vhdl_cassign_stmt(ref, priv->const_driver)); (new vhdl_cassign_stmt(ref, priv->const_driver));
priv->const_driver = NULL; priv->const_driver = NULL;
@ -1085,7 +1065,7 @@ extern "C" int draw_constant_drivers(ivl_scope_t scope, void *_parent)
scope_nexus_t *sn = visible_nexus(priv, arch_scope); scope_nexus_t *sn = visible_nexus(priv, arch_scope);
// Make sure we don't drive inputs // Make sure we don't drive inputs
if (ivl_signal_port(sn->sig) != IVL_SIP_INPUT) { if (ivl_signal_port(sn->sig) != IVL_SIP_INPUT) {
for (list<ivl_signal_t>::const_iterator it = sn->connect.begin(); for (list<ivl_signal_t>::const_iterator it = sn->connect.begin();
it != sn->connect.end(); it != sn->connect.end();
++it) { ++it) {
@ -1095,20 +1075,20 @@ extern "C" int draw_constant_drivers(ivl_scope_t scope, void *_parent)
vhdl_type* ltype = vhdl_type* ltype =
vhdl_type::type_for(ivl_signal_width(*it), vhdl_type::type_for(ivl_signal_width(*it),
ivl_signal_signed(*it)); ivl_signal_signed(*it));
vhdl_var_ref *rref = vhdl_var_ref *rref =
new vhdl_var_ref(get_renamed_signal(sn->sig).c_str(), rtype); new vhdl_var_ref(get_renamed_signal(sn->sig).c_str(), rtype);
vhdl_var_ref *lref = vhdl_var_ref *lref =
new vhdl_var_ref(get_renamed_signal(*it).c_str(), ltype); new vhdl_var_ref(get_renamed_signal(*it).c_str(), ltype);
// Make sure the LHS and RHS have the same type // Make sure the LHS and RHS have the same type
vhdl_expr* rhs = rref->cast(lref->get_type()); vhdl_expr* rhs = rref->cast(lref->get_type());
ent->get_arch()->add_stmt(new vhdl_cassign_stmt(lref, rhs)); ent->get_arch()->add_stmt(new vhdl_cassign_stmt(lref, rhs));
} }
} }
sn->connect.clear(); sn->connect.clear();
} }
} }
} }
@ -1119,7 +1099,7 @@ extern "C" int draw_all_logic_and_lpm(ivl_scope_t scope, void *_parent)
{ {
if (!is_default_scope_instance(scope)) if (!is_default_scope_instance(scope))
return 0; // Not interested in this instance return 0; // Not interested in this instance
if (ivl_scope_type(scope) == IVL_SCT_MODULE) { if (ivl_scope_type(scope) == IVL_SCT_MODULE) {
vhdl_entity *ent = find_entity(scope); vhdl_entity *ent = find_entity(scope);
assert(ent); assert(ent);
@ -1130,40 +1110,40 @@ extern "C" int draw_all_logic_and_lpm(ivl_scope_t scope, void *_parent)
declare_lpm(ent->get_arch(), scope); declare_lpm(ent->get_arch(), scope);
} }
set_active_entity(NULL); set_active_entity(NULL);
} }
return ivl_scope_children(scope, draw_all_logic_and_lpm, scope); return ivl_scope_children(scope, draw_all_logic_and_lpm, scope);
} }
extern "C" int draw_hierarchy(ivl_scope_t scope, void *_parent) extern "C" int draw_hierarchy(ivl_scope_t scope, void *_parent)
{ {
if (ivl_scope_type(scope) == IVL_SCT_MODULE && _parent) { if (ivl_scope_type(scope) == IVL_SCT_MODULE && _parent) {
ivl_scope_t parent = static_cast<ivl_scope_t>(_parent); ivl_scope_t parent = static_cast<ivl_scope_t>(_parent);
// Skip over any containing generate scopes // Skip over any containing generate scopes
while (ivl_scope_type(parent) == IVL_SCT_GENERATE) while (ivl_scope_type(parent) == IVL_SCT_GENERATE)
parent = ivl_scope_parent(parent); parent = ivl_scope_parent(parent);
if (!is_default_scope_instance(parent)) if (!is_default_scope_instance(parent))
return 0; // Not generating code for the parent instance so return 0; // Not generating code for the parent instance so
// don't generate for the child // don't generate for the child
vhdl_entity *ent = find_entity(scope); vhdl_entity *ent = find_entity(scope);
assert(ent); assert(ent);
vhdl_entity *parent_ent = find_entity(parent); vhdl_entity *parent_ent = find_entity(parent);
assert(parent_ent); assert(parent_ent);
vhdl_arch *parent_arch = parent_ent->get_arch(); vhdl_arch *parent_arch = parent_ent->get_arch();
assert(parent_arch != NULL); assert(parent_arch != NULL);
// Create a forward declaration for it // Create a forward declaration for it
vhdl_scope *parent_scope = parent_arch->get_scope(); vhdl_scope *parent_scope = parent_arch->get_scope();
if (!parent_scope->have_declared(ent->get_name())) { if (!parent_scope->have_declared(ent->get_name())) {
vhdl_decl *comp_decl = vhdl_component_decl::component_decl_for(ent); vhdl_decl *comp_decl = vhdl_component_decl::component_decl_for(ent);
parent_arch->get_scope()->add_decl(comp_decl); parent_arch->get_scope()->add_decl(comp_decl);
} }
// And an instantiation statement // And an instantiation statement
string inst_name(ivl_scope_basename(scope)); string inst_name(ivl_scope_basename(scope));
inst_name += genvar_unique_suffix(ivl_scope_parent(scope)); inst_name += genvar_unique_suffix(ivl_scope_parent(scope));
@ -1174,13 +1154,13 @@ extern "C" int draw_hierarchy(ivl_scope_t scope, void *_parent)
// Would produce an invalid instance name // Would produce an invalid instance name
inst_name += "_inst"; inst_name += "_inst";
} }
// Need to replace any [ and ] characters that result // Need to replace any [ and ] characters that result
// from generate statements // from generate statements
string::size_type loc = inst_name.find('[', 0); string::size_type loc = inst_name.find('[', 0);
if (loc != string::npos) if (loc != string::npos)
inst_name.erase(loc, 1); inst_name.erase(loc, 1);
loc = inst_name.find(']', 0); loc = inst_name.find(']', 0);
if (loc != string::npos) if (loc != string::npos)
inst_name.erase(loc, 1); inst_name.erase(loc, 1);
@ -1197,7 +1177,7 @@ extern "C" int draw_hierarchy(ivl_scope_t scope, void *_parent)
// Make sure the name doesn't collide with anything we've // Make sure the name doesn't collide with anything we've
// already declared // already declared
avoid_name_collision(inst_name, parent_arch->get_scope()); avoid_name_collision(inst_name, parent_arch->get_scope());
vhdl_comp_inst *inst = vhdl_comp_inst *inst =
new vhdl_comp_inst(inst_name.c_str(), ent->get_name().c_str()); new vhdl_comp_inst(inst_name.c_str(), ent->get_name().c_str());
port_map(scope, parent_ent, inst); port_map(scope, parent_ent, inst);
@ -1206,15 +1186,15 @@ extern "C" int draw_hierarchy(ivl_scope_t scope, void *_parent)
ss << "Generated from instantiation at " ss << "Generated from instantiation at "
<< ivl_scope_file(scope) << ":" << ivl_scope_lineno(scope); << ivl_scope_file(scope) << ":" << ivl_scope_lineno(scope);
inst->set_comment(ss.str().c_str()); inst->set_comment(ss.str().c_str());
parent_arch->add_stmt(inst); parent_arch->add_stmt(inst);
} }
return ivl_scope_children(scope, draw_hierarchy, scope); return ivl_scope_children(scope, draw_hierarchy, scope);
} }
int draw_scope(ivl_scope_t scope, void *_parent) int draw_scope(ivl_scope_t scope, void *_parent)
{ {
int rc = draw_skeleton_scope(scope, _parent); int rc = draw_skeleton_scope(scope, _parent);
if (rc != 0) if (rc != 0)
return rc; return rc;
@ -1225,7 +1205,7 @@ int draw_scope(ivl_scope_t scope, void *_parent)
rc = draw_all_logic_and_lpm(scope, _parent); rc = draw_all_logic_and_lpm(scope, _parent);
if (rc != 0) if (rc != 0)
return rc; return rc;
rc = draw_hierarchy(scope, _parent); rc = draw_hierarchy(scope, _parent);
if (rc != 0) if (rc != 0)
@ -1238,7 +1218,7 @@ int draw_scope(ivl_scope_t scope, void *_parent)
rc = draw_constant_drivers(scope, _parent); rc = draw_constant_drivers(scope, _parent);
if (rc != 0) if (rc != 0)
return rc; return rc;
return 0; return 0;
} }

View File

@ -25,9 +25,8 @@
#include <algorithm> #include <algorithm>
#include <string> #include <string>
#include <map> #include <map>
#include <vector> #include <set>
#include <cstring> #include <cstring>
#include <iostream>
using namespace std; using namespace std;
@ -54,7 +53,7 @@ using namespace std;
* provides a mechanism for renaming signals -- i.e. when * provides a mechanism for renaming signals -- i.e. when
* an output has the same name as register: valid in Verilog * an output has the same name as register: valid in Verilog
* but not in VHDL, so two separate signals need to be * but not in VHDL, so two separate signals need to be
* defined. * defined.
*/ */
struct signal_defn_t { struct signal_defn_t {
std::string renamed; // The name of the VHDL signal std::string renamed; // The name of the VHDL signal
@ -65,10 +64,10 @@ struct signal_defn_t {
// These are stored in a list rather than a set so the first // These are stored in a list rather than a set so the first
// entity added will correspond to the first (top) Verilog module // entity added will correspond to the first (top) Verilog module
// encountered and hence it will appear first in the output file. // encountered and hence it will appear first in the output file.
static entity_list_t g_entities; static entity_list_t g_entities;
// Store the mapping of ivl scope names to entity names // Store the mapping of ivl scope names to entity names
typedef map<ivl_scope_t, string> scope_name_map_t; typedef map<string, string> scope_name_map_t;
static scope_name_map_t g_scope_names; static scope_name_map_t g_scope_names;
typedef std::map<ivl_signal_t, signal_defn_t> signal_defn_map_t; typedef std::map<ivl_signal_t, signal_defn_t> signal_defn_map_t;
@ -78,9 +77,10 @@ static vhdl_entity *g_active_entity = NULL;
// Set of scopes that are treated as the default examples of // Set of scopes that are treated as the default examples of
// that type. Any other scopes of the same type are ignored. // that type. Any other scopes of the same type are ignored.
typedef vector<ivl_scope_t> default_scopes_t; typedef set<ivl_scope_t> default_scopes_t;
static default_scopes_t g_default_scopes; static default_scopes_t g_default_scopes;
// True if signal `sig' has already been encountered by the code // True if signal `sig' has already been encountered by the code
// generator. This means we have already assigned it to a VHDL code // generator. This means we have already assigned it to a VHDL code
// object and possibly renamed it. // object and possibly renamed it.
@ -145,7 +145,7 @@ ivl_signal_t find_signal_named(const std::string &name, const vhdl_scope *scope)
// Compare the name of an entity against a string // Compare the name of an entity against a string
struct cmp_ent_name { struct cmp_ent_name {
cmp_ent_name(const string& n) : name_(n) {} cmp_ent_name(const string& n) : name_(n) {}
bool operator()(const vhdl_entity* ent) const bool operator()(const vhdl_entity* ent) const
{ {
return ent->get_name() == name_; return ent->get_name() == name_;
@ -156,7 +156,7 @@ struct cmp_ent_name {
// Find an entity given its name. // Find an entity given its name.
vhdl_entity* find_entity(const string& name) vhdl_entity* find_entity(const string& name)
{ {
entity_list_t::const_iterator it entity_list_t::const_iterator it
= find_if(g_entities.begin(), g_entities.end(), = find_if(g_entities.begin(), g_entities.end(),
cmp_ent_name(name)); cmp_ent_name(name));
@ -176,34 +176,21 @@ vhdl_entity* find_entity(ivl_scope_t scope)
// Skip over generate scopes // Skip over generate scopes
while (ivl_scope_type(scope) == IVL_SCT_GENERATE) while (ivl_scope_type(scope) == IVL_SCT_GENERATE)
scope = ivl_scope_parent(scope); scope = ivl_scope_parent(scope);
assert(ivl_scope_type(scope) == IVL_SCT_MODULE); assert(ivl_scope_type(scope) == IVL_SCT_MODULE);
if (is_default_scope_instance(scope)) { scope_name_map_t::iterator it = g_scope_names.find(ivl_scope_tname(scope));
scope_name_map_t::iterator it = g_scope_names.find(scope); if (it != g_scope_names.end())
if (it != g_scope_names.end()) return find_entity((*it).second);
return find_entity((*it).second); else
else
return NULL;
}
else {
const char *tname = ivl_scope_tname(scope);
for (scope_name_map_t::iterator it = g_scope_names.begin();
it != g_scope_names.end(); ++it) {
if (strcmp(tname, ivl_scope_tname((*it).first)) == 0)
return find_entity((*it).second);
}
return NULL; return NULL;
}
} }
// Add an entity/architecture pair to the list of entities to emit. // Add an entity/architecture pair to the list of entities to emit.
void remember_entity(vhdl_entity* ent, ivl_scope_t scope) void remember_entity(vhdl_entity* ent, ivl_scope_t scope)
{ {
g_entities.push_back(ent); g_entities.push_back(ent);
g_scope_names[scope] = ent->get_name(); g_scope_names[ivl_scope_tname(scope)] = ent->get_name();
} }
// Print all VHDL entities, in order, to the specified output stream. // Print all VHDL entities, in order, to the specified output stream.
@ -226,7 +213,7 @@ void free_all_vhdl_objects()
size_t total = vhdl_element::total_allocated(); size_t total = vhdl_element::total_allocated();
debug_msg("%d total bytes used for VHDL syntax objects", total); debug_msg("%d total bytes used for VHDL syntax objects", total);
g_entities.clear(); g_entities.clear();
} }
@ -241,52 +228,12 @@ void set_active_entity(vhdl_entity *ent)
{ {
g_active_entity = ent; g_active_entity = ent;
} }
/* /*
* True if two scopes have the same type name. * True if two scopes have the same type name.
*/ */
static bool same_scope_type_name(ivl_scope_t a, ivl_scope_t b) static bool same_scope_type_name(ivl_scope_t a, ivl_scope_t b)
{ {
if (strcmp(ivl_scope_tname(a), ivl_scope_tname(b)) != 0) return strcmp(ivl_scope_tname(a), ivl_scope_tname(b)) == 0;
return false;
unsigned nparams_a = ivl_scope_params(a);
unsigned nparams_b = ivl_scope_params(b);
if (nparams_a != nparams_b)
return false;
for (unsigned i = 0; i < nparams_a; i++) {
ivl_parameter_t param_a = ivl_scope_param(a, i);
ivl_parameter_t param_b = ivl_scope_param(b, i);
if (strcmp(ivl_parameter_basename(param_a),
ivl_parameter_basename(param_b)) != 0)
return false;
ivl_expr_t value_a = ivl_parameter_expr(param_a);
ivl_expr_t value_b = ivl_parameter_expr(param_b);
if (ivl_expr_type(value_a) != ivl_expr_type(value_b))
return false;
switch (ivl_expr_type(value_a)) {
case IVL_EX_STRING:
if (strcmp(ivl_expr_string(value_a), ivl_expr_string(value_b)) != 0)
return false;
break;
case IVL_EX_NUMBER:
if (ivl_expr_uvalue(value_a) != ivl_expr_uvalue(value_b))
return false;
break;
default:
assert(false);
}
}
return true;
} }
/* /*
@ -299,7 +246,7 @@ bool seen_this_scope_type(ivl_scope_t s)
if (find_if(g_default_scopes.begin(), g_default_scopes.end(), if (find_if(g_default_scopes.begin(), g_default_scopes.end(),
bind1st(ptr_fun(same_scope_type_name), s)) bind1st(ptr_fun(same_scope_type_name), s))
== g_default_scopes.end()) { == g_default_scopes.end()) {
g_default_scopes.push_back(s); g_default_scopes.insert(s);
return false; return false;
} }
else else

View File

@ -1,7 +1,7 @@
/* /*
* VHDL code generation for statements. * VHDL code generation for statements.
* *
* Copyright (C) 2008-2010 Nick Gasson (nick@nickg.me.uk) * Copyright (C) 2008-2009 Nick Gasson (nick@nickg.me.uk)
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -30,9 +30,6 @@
#include <set> #include <set>
#include <algorithm> #include <algorithm>
static void emit_wait_for_0(vhdl_procedural *proc, stmt_container *container,
ivl_statement_t stmt, vhdl_expr *expr);
/* /*
* VHDL has no real equivalent of Verilog's $finish task. The * VHDL has no real equivalent of Verilog's $finish task. The
* current solution is to use `assert false ...' to terminate * current solution is to use `assert false ...' to terminate
@ -43,7 +40,7 @@ static void emit_wait_for_0(vhdl_procedural *proc, stmt_container *container,
* An alternative is to use the VHPI interface supported by * An alternative is to use the VHPI interface supported by
* some VHDL simulators and implement the $finish functionality * some VHDL simulators and implement the $finish functionality
* in C. This function can be enabled with the flag * in C. This function can be enabled with the flag
* -puse-vhpi-finish=1. * -puse-vhpi-finish=1.
*/ */
static int draw_stask_finish(vhdl_procedural *proc, stmt_container *container, static int draw_stask_finish(vhdl_procedural *proc, stmt_container *container,
ivl_statement_t stmt) ivl_statement_t stmt)
@ -54,111 +51,9 @@ static int draw_stask_finish(vhdl_procedural *proc, stmt_container *container,
container->add_stmt(new vhdl_pcall_stmt("work.Verilog_Support.Finish")); container->add_stmt(new vhdl_pcall_stmt("work.Verilog_Support.Finish"));
} }
else { else {
container->add_stmt( container->add_stmt(new vhdl_assert_stmt("SIMULATION FINISHED"));
new vhdl_report_stmt(new vhdl_const_string("SIMULATION FINISHED"),
SEVERITY_FAILURE));
}
return 0;
}
static char parse_octal(const char *p)
{
assert(*p && *(p+1) && *(p+2));
assert(isdigit(*p) && isdigit(*(p+1)) && isdigit(*(p+1)));
return (*p - '0') * 64
+ (*(p+1) - '0') * 8
+ (*(p+2) - '0') * 1;
}
// Generate VHDL report statements for Verilog $display/$write
static int draw_stask_display(vhdl_procedural *proc,
stmt_container *container,
ivl_statement_t stmt)
{
vhdl_binop_expr *text = new vhdl_binop_expr(VHDL_BINOP_CONCAT,
vhdl_type::string());
const int count = ivl_stmt_parm_count(stmt);
int i = 0;
while (i < count) {
// $display may have an empty parameter, in which case
// the expression will be null
// The behaviour here seems to be to output a space
ivl_expr_t net = ivl_stmt_parm(stmt, i++);
if (net == NULL) {
text->add_expr(new vhdl_const_string(" "));
continue;
}
if (ivl_expr_type(net) == IVL_EX_STRING) {
ostringstream ss;
for (const char *p = ivl_expr_string(net); *p; p++) {
if (*p == '\\') {
// Octal escape
char ch = parse_octal(p+1);
if (ch == '\n') {
// Is there a better way of handling newlines?
// Maybe generate another report statement
}
else
ss << ch;
p += 3;
}
else if (*p == '%' && *(++p) != '%') {
// Flush the output string up to this point
text->add_expr(new vhdl_const_string(ss.str()));
ss.str("");
// Skip over width for now
while (isdigit(*p)) ++p;
switch (*p) {
case 'm':
// TOOD: we can get the module name via attributes
cerr << "Warning: no VHDL translation for %m format code"
<< endl;
break;
default:
{
assert(i < count);
ivl_expr_t netp = ivl_stmt_parm(stmt, i++);
assert(netp);
vhdl_expr *base = translate_expr(netp);
if (NULL == base)
return 1;
emit_wait_for_0(proc, container, stmt, base);
text->add_expr(base->cast(text->get_type()));
}
}
}
else
ss << *p;
}
// Emit any non-empty string data left in the buffer
if (!ss.str().empty())
text->add_expr(new vhdl_const_string(ss.str()));
}
else {
vhdl_expr *base = translate_expr(net);
if (NULL == base)
return 1;
emit_wait_for_0(proc, container, stmt, base);
text->add_expr(base->cast(text->get_type()));
}
} }
if (count == 0)
text->add_expr(new vhdl_const_string(""));
container->add_stmt(new vhdl_report_stmt(text));
return 0; return 0;
} }
@ -172,9 +67,9 @@ static int draw_stask(vhdl_procedural *proc, stmt_container *container,
const char *name = ivl_stmt_name(stmt); const char *name = ivl_stmt_name(stmt);
if (strcmp(name, "$display") == 0) if (strcmp(name, "$display") == 0)
return draw_stask_display(proc, container, stmt); return draw_stask_display(proc, container, stmt, true);
else if (strcmp(name, "$write") == 0) else if (strcmp(name, "$write") == 0)
return draw_stask_display(proc, container, stmt); return draw_stask_display(proc, container, stmt, false);
else if (strcmp(name, "$finish") == 0) else if (strcmp(name, "$finish") == 0)
return draw_stask_finish(proc, container, stmt); return draw_stask_finish(proc, container, stmt);
else { else {
@ -198,7 +93,7 @@ static int draw_stask(vhdl_procedural *proc, stmt_container *container,
* *
* If this block has its own scope with local variables then these * If this block has its own scope with local variables then these
* are added to the process as local variables and the statements * are added to the process as local variables and the statements
* are generated as above. * are generated as above.
*/ */
static int draw_block(vhdl_procedural *proc, stmt_container *container, static int draw_block(vhdl_procedural *proc, stmt_container *container,
ivl_statement_t stmt, bool is_last) ivl_statement_t stmt, bool is_last)
@ -216,7 +111,7 @@ static int draw_block(vhdl_procedural *proc, stmt_container *container,
(new vhdl_var_decl(make_safe_name(sig), type)); (new vhdl_var_decl(make_safe_name(sig), type));
} }
} }
int count = ivl_stmt_block_count(stmt); int count = ivl_stmt_block_count(stmt);
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
ivl_statement_t stmt_i = ivl_stmt_block_stmt(stmt, i); ivl_statement_t stmt_i = ivl_stmt_block_stmt(stmt, i);
@ -236,6 +131,27 @@ static int draw_noop(vhdl_procedural *proc, stmt_container *container,
return 0; return 0;
} }
/*
* The VHDL code generator inserts `wait for 0 ns' after each
* not-last-in-block blocking assignment.
* If this is immediately followed by another `wait for ...' then
* we might as well not emit the first zero-time wait.
*/
void prune_wait_for_0(stmt_container *container)
{
vhdl_wait_stmt *wait0;
stmt_container::stmt_list_t &stmts = container->get_stmts();
while (stmts.size() > 0
&& (wait0 = dynamic_cast<vhdl_wait_stmt*>(stmts.back()))) {
if (wait0->get_type() == VHDL_WAIT_FOR0) {
delete wait0;
stmts.pop_back();
}
else
break;
}
}
static vhdl_var_ref *make_assign_lhs(ivl_lval_t lval, vhdl_scope *scope) static vhdl_var_ref *make_assign_lhs(ivl_lval_t lval, vhdl_scope *scope)
{ {
ivl_signal_t sig = ivl_lval_sig(lval); ivl_signal_t sig = ivl_lval_sig(lval);
@ -251,13 +167,13 @@ static vhdl_var_ref *make_assign_lhs(ivl_lval_t lval, vhdl_scope *scope)
if (e_off) { if (e_off) {
if ((base = translate_expr(e_off)) == NULL) if ((base = translate_expr(e_off)) == NULL)
return NULL; return NULL;
vhdl_type integer(VHDL_TYPE_INTEGER); vhdl_type integer(VHDL_TYPE_INTEGER);
base = base->cast(&integer); base = base->cast(&integer);
} }
unsigned lval_width = ivl_lval_width(lval); unsigned lval_width = ivl_lval_width(lval);
string signame(get_renamed_signal(sig)); string signame(get_renamed_signal(sig));
vhdl_decl *decl = scope->get_decl(signame); vhdl_decl *decl = scope->get_decl(signame);
assert(decl); assert(decl);
@ -281,7 +197,7 @@ static vhdl_var_ref *make_assign_lhs(ivl_lval_t lval, vhdl_scope *scope)
// ...and use this new variable as the assignment LHS // ...and use this new variable as the assignment LHS
decl = shadow_decl; decl = shadow_decl;
} }
vhdl_type *ltype = new vhdl_type(*decl->get_type()); vhdl_type *ltype = new vhdl_type(*decl->get_type());
vhdl_var_ref *lval_ref = new vhdl_var_ref(decl->get_name(), ltype); vhdl_var_ref *lval_ref = new vhdl_var_ref(decl->get_name(), ltype);
if (base) { if (base) {
@ -305,7 +221,7 @@ static bool assignment_lvals(ivl_statement_t stmt, vhdl_procedural *proc,
return false; return false;
lvals.push_back(lhs); lvals.push_back(lhs);
} }
return true; return true;
} }
@ -323,7 +239,7 @@ assign_for(vhdl_decl::assign_type_t atype, vhdl_var_ref *lhs, vhdl_expr *rhs)
return new vhdl_assign_stmt(lhs, rhs); return new vhdl_assign_stmt(lhs, rhs);
case vhdl_decl::ASSIGN_NONBLOCK: case vhdl_decl::ASSIGN_NONBLOCK:
return new vhdl_nbassign_stmt(lhs, rhs); return new vhdl_nbassign_stmt(lhs, rhs);
} }
assert(false); assert(false);
return NULL; return NULL;
} }
@ -347,68 +263,12 @@ bool check_valid_assignment(vhdl_decl::assign_type_t atype, vhdl_procedural *pro
return true; return true;
} }
// Generate a "wait for 0 ns" statement to emulate the behaviour of
// Verilog blocking assignment using VHDL signals. This is only generated
// if we read from the target of a blocking assignment in the same
// process (i.e. it is only generated when required, not for every
// blocking assignment). An example:
//
// begin
// x = 5;
// if (x == 2)
// y = 7;
// end
//
// Becomes:
//
// x <= 5;
// wait for 0 ns; -- Required to implement assignment semantics
// if x = 2 then
// y <= 7; -- No need for wait here, not read
// end if;
//
static void emit_wait_for_0(vhdl_procedural *proc,
stmt_container *container,
ivl_statement_t stmt,
vhdl_expr *expr)
{
vhdl_var_set_t read;
expr->find_vars(read);
bool need_wait_for_0 = false;
for (vhdl_var_set_t::const_iterator it = read.begin();
it != read.end(); ++it) {
if (proc->is_blocking_target(*it))
need_wait_for_0 = true;
}
stmt_container::stmt_list_t &stmts = container->get_stmts();
bool last_was_wait =
!stmts.empty() && dynamic_cast<vhdl_wait_stmt*>(stmts.back());
if (need_wait_for_0 && !last_was_wait) {
debug_msg("Generated wait-for-0 for %s:%d",
ivl_stmt_file(stmt), ivl_stmt_lineno(stmt));
vhdl_seq_stmt *wait = new vhdl_wait_stmt(VHDL_WAIT_FOR0);
ostringstream ss;
ss << "Read target of blocking assignment ("
<< ivl_stmt_file(stmt)
<< ":" << ivl_stmt_lineno(stmt) << ")";
wait->set_comment(ss.str());
container->add_stmt(wait);
proc->added_wait_stmt();
}
}
// Generate an assignment of type T for the Verilog statement stmt. // Generate an assignment of type T for the Verilog statement stmt.
// If a statement was generated then `assign_type' will contain the // If a statement was generated then `assign_type' will contain the
// type of assignment that was generated; this should be initialised // type of assignment that was generated; this should be initialised
// to some sensible default. // to some sensible default.
void make_assignment(vhdl_procedural *proc, stmt_container *container, void make_assignment(vhdl_procedural *proc, stmt_container *container,
ivl_statement_t stmt, bool emul_blocking, ivl_statement_t stmt, bool blocking,
vhdl_decl::assign_type_t& assign_type) vhdl_decl::assign_type_t& assign_type)
{ {
list<vhdl_var_ref*> lvals; list<vhdl_var_ref*> lvals;
@ -426,23 +286,14 @@ void make_assignment(vhdl_procedural *proc, stmt_container *container,
if (rhs == NULL) if (rhs == NULL)
return; return;
emit_wait_for_0(proc, container, stmt, rhs);
if (rhs2)
emit_wait_for_0(proc, container, stmt, rhs2);
if (lvals.size() == 1) { if (lvals.size() == 1) {
vhdl_var_ref *lhs = lvals.front(); vhdl_var_ref *lhs = lvals.front();
rhs = rhs->cast(lhs->get_type()); rhs = rhs->cast(lhs->get_type());
ivl_expr_t i_delay; ivl_expr_t i_delay;
vhdl_expr *after = NULL; vhdl_expr *after = NULL;
if ((i_delay = ivl_stmt_delay_expr(stmt)) != NULL) { if ((i_delay = ivl_stmt_delay_expr(stmt)) != NULL)
after = translate_time_expr(i_delay); after = translate_time_expr(i_delay);
if (after == NULL)
return;
emit_wait_for_0(proc, container, stmt, after);
}
// Find the declaration of the LHS so we know what type // Find the declaration of the LHS so we know what type
// of assignment statement to generate (is it a signal, // of assignment statement to generate (is it a signal,
@ -450,9 +301,6 @@ void make_assignment(vhdl_procedural *proc, stmt_container *container,
vhdl_decl *decl = proc->get_scope()->get_decl(lhs->get_name()); vhdl_decl *decl = proc->get_scope()->get_decl(lhs->get_name());
assign_type = decl->assignment_type(); assign_type = decl->assignment_type();
if (assign_type == vhdl_decl::ASSIGN_NONBLOCK && emul_blocking)
proc->add_blocking_target(lhs);
// A small optimisation is to expand ternary RHSs into an // A small optimisation is to expand ternary RHSs into an
// if statement (eliminates a function call and produces // if statement (eliminates a function call and produces
// more idiomatic code) // more idiomatic code)
@ -460,13 +308,11 @@ void make_assignment(vhdl_procedural *proc, stmt_container *container,
rhs2 = rhs2->cast(lhs->get_type()); rhs2 = rhs2->cast(lhs->get_type());
vhdl_var_ref *lhs2 = vhdl_var_ref *lhs2 =
make_assign_lhs(ivl_stmt_lval(stmt, 0), proc->get_scope()); make_assign_lhs(ivl_stmt_lval(stmt, 0), proc->get_scope());
vhdl_expr *test = translate_expr(ivl_expr_oper1(rval)); vhdl_expr *test = translate_expr(ivl_expr_oper1(rval));
if (NULL == test) if (NULL == test)
return; return;
emit_wait_for_0(proc, container, stmt, test);
if (!check_valid_assignment(decl->assignment_type(), proc, stmt)) if (!check_valid_assignment(decl->assignment_type(), proc, stmt))
return; return;
@ -498,7 +344,7 @@ void make_assignment(vhdl_procedural *proc, stmt_container *container,
// declaration as initialisers. This optimisation is only // declaration as initialisers. This optimisation is only
// performed on assignments of constant values to prevent // performed on assignments of constant values to prevent
// ordering problems. // ordering problems.
// This also has another application: If this is an `initial' // This also has another application: If this is an `initial'
// process and we haven't yet generated a `wait' statement then // process and we haven't yet generated a `wait' statement then
// moving the assignment to the initialization preserves the // moving the assignment to the initialization preserves the
@ -514,7 +360,7 @@ void make_assignment(vhdl_procedural *proc, stmt_container *container,
&& !decl->has_initial() && !decl->has_initial()
&& rhs->constant() && rhs->constant()
&& decl->get_type()->get_name() != VHDL_TYPE_ARRAY) { && decl->get_type()->get_name() != VHDL_TYPE_ARRAY) {
// If this assignment is not in the top-level container // If this assignment is not in the top-level container
// it will not be made on all paths through the code // it will not be made on all paths through the code
// This precludes any future extraction of an initialiser // This precludes any future extraction of an initialiser
@ -522,7 +368,6 @@ void make_assignment(vhdl_procedural *proc, stmt_container *container,
decl->set_initial(NULL); // Default initial value decl->set_initial(NULL); // Default initial value
else { else {
decl->set_initial(rhs); decl->set_initial(rhs);
proc->get_scope()->hoisted_initialiser(true);
delete lhs; delete lhs;
return; return;
} }
@ -534,8 +379,8 @@ void make_assignment(vhdl_procedural *proc, stmt_container *container,
vhdl_abstract_assign_stmt *a = vhdl_abstract_assign_stmt *a =
assign_for(decl->assignment_type(), lhs, rhs); assign_for(decl->assignment_type(), lhs, rhs);
container->add_stmt(a); container->add_stmt(a);
if (after != NULL) if (after != NULL)
a->set_after(after); a->set_after(after);
} }
else { else {
@ -551,25 +396,20 @@ void make_assignment(vhdl_procedural *proc, stmt_container *container,
proc->get_scope()->add_decl(tmp_decl); proc->get_scope()->add_decl(tmp_decl);
container->add_stmt(new vhdl_assign_stmt(tmp_decl->make_ref(), rhs)); container->add_stmt(new vhdl_assign_stmt(tmp_decl->make_ref(), rhs));
list<vhdl_var_ref*>::iterator it; list<vhdl_var_ref*>::iterator it;
int width_so_far = 0; int width_so_far = 0;
for (it = lvals.begin(); it != lvals.end(); ++it) { for (it = lvals.begin(); it != lvals.end(); ++it) {
vhdl_var_ref *tmp_rhs = tmp_decl->make_ref(); vhdl_var_ref *tmp_rhs = tmp_decl->make_ref();
int lval_width = (*it)->get_type()->get_width(); int lval_width = (*it)->get_type()->get_width();
vhdl_expr *slice_base = new vhdl_const_int(width_so_far); vhdl_expr *slice_base = new vhdl_const_int(width_so_far);
tmp_rhs->set_slice(slice_base, lval_width - 1); tmp_rhs->set_slice(slice_base, lval_width - 1);
ivl_expr_t i_delay; ivl_expr_t i_delay;
vhdl_expr *after = NULL; vhdl_expr *after = NULL;
if ((i_delay = ivl_stmt_delay_expr(stmt)) != NULL) { if ((i_delay = ivl_stmt_delay_expr(stmt)) != NULL)
after = translate_time_expr(i_delay); after = translate_time_expr(i_delay);
if (after == NULL)
return;
emit_wait_for_0(proc, container, stmt, after);
}
// Find the declaration of the LHS so we know what type // Find the declaration of the LHS so we know what type
// of assignment statement to generate (is it a signal, // of assignment statement to generate (is it a signal,
@ -579,7 +419,7 @@ void make_assignment(vhdl_procedural *proc, stmt_container *container,
if (!check_valid_assignment(decl->assignment_type(), proc, stmt)) if (!check_valid_assignment(decl->assignment_type(), proc, stmt))
return; return;
vhdl_abstract_assign_stmt *a = vhdl_abstract_assign_stmt *a =
assign_for(decl->assignment_type(), *it, tmp_rhs); assign_for(decl->assignment_type(), *it, tmp_rhs);
if (after) if (after)
@ -588,11 +428,10 @@ void make_assignment(vhdl_procedural *proc, stmt_container *container,
container->add_stmt(a); container->add_stmt(a);
width_so_far += lval_width; width_so_far += lval_width;
if (assign_type == vhdl_decl::ASSIGN_NONBLOCK && emul_blocking)
proc->add_blocking_target(*it);
} }
} }
return;
} }
/* /*
@ -615,10 +454,26 @@ static int draw_assign(vhdl_procedural *proc, stmt_container *container,
ivl_statement_t stmt, bool is_last) ivl_statement_t stmt, bool is_last)
{ {
vhdl_decl::assign_type_t assign_type = vhdl_decl::ASSIGN_NONBLOCK; vhdl_decl::assign_type_t assign_type = vhdl_decl::ASSIGN_NONBLOCK;
bool emulate_blocking = proc->get_scope()->allow_signal_assignment(); if (proc->get_scope()->allow_signal_assignment()) {
// Blocking assignment is implemented as non-blocking assignment
make_assignment(proc, container, stmt, emulate_blocking, assign_type); // followed by a zero-time wait
// This follows the Verilog semantics fairly closely.
make_assignment(proc, container, stmt, false, assign_type);
// Don't generate a zero-wait if either:
// a) this is the last statement in the process
// c) a blocking assignment was generated
if (!is_last && assign_type == vhdl_decl::ASSIGN_NONBLOCK) {
prune_wait_for_0(container);
container->add_stmt
(new vhdl_wait_stmt(VHDL_WAIT_FOR0));
proc->added_wait_stmt();
}
}
else
make_assignment(proc, container, stmt, true, assign_type);
return 0; return 0;
} }
@ -646,7 +501,9 @@ static int draw_delay(vhdl_procedural *proc, stmt_container *container,
if (NULL == time) if (NULL == time)
return 1; return 1;
} }
prune_wait_for_0(container);
ivl_statement_t sub_stmt = ivl_stmt_sub_stmt(stmt); ivl_statement_t sub_stmt = ivl_stmt_sub_stmt(stmt);
vhdl_wait_stmt *wait = vhdl_wait_stmt *wait =
new vhdl_wait_stmt(VHDL_WAIT_FOR, time); new vhdl_wait_stmt(VHDL_WAIT_FOR, time);
@ -654,7 +511,7 @@ static int draw_delay(vhdl_procedural *proc, stmt_container *container,
// Remember that we needed a wait statement so if this is // Remember that we needed a wait statement so if this is
// a process it cannot have a sensitivity list // a process it cannot have a sensitivity list
proc->added_wait_stmt(); proc->added_wait_stmt();
container->add_stmt(wait); container->add_stmt(wait);
// Expand the sub-statement as well // Expand the sub-statement as well
@ -662,12 +519,12 @@ static int draw_delay(vhdl_procedural *proc, stmt_container *container,
// is caught here instead // is caught here instead
if (ivl_statement_type(sub_stmt) != IVL_ST_NOOP) if (ivl_statement_type(sub_stmt) != IVL_ST_NOOP)
draw_stmt(proc, container, sub_stmt); draw_stmt(proc, container, sub_stmt);
// Any further assignments occur after simulation time 0 // Any further assignments occur after simulation time 0
// so they cannot be used to initialise signal declarations // so they cannot be used to initialise signal declarations
// (if this scope is an initial process) // (if this scope is an initial process)
proc->get_scope()->set_initializing(false); proc->get_scope()->set_initializing(false);
return 0; return 0;
} }
@ -725,19 +582,19 @@ static bool draw_synthesisable_wait(vhdl_process *proc, stmt_container *containe
{ {
// At the moment this only detects FFs with an asynchronous reset // At the moment this only detects FFs with an asynchronous reset
// All other code will fall back on the default draw_wait // All other code will fall back on the default draw_wait
// Store a set of the edge triggered signals // Store a set of the edge triggered signals
// The second item is true if this is positive-edge // The second item is true if this is positive-edge
set<ivl_nexus_t> edge_triggered; set<ivl_nexus_t> edge_triggered;
const int nevents = ivl_stmt_nevent(stmt); const int nevents = ivl_stmt_nevent(stmt);
for (int i = 0; i < nevents; i++) { for (int i = 0; i < nevents; i++) {
ivl_event_t event = ivl_stmt_events(stmt, i); ivl_event_t event = ivl_stmt_events(stmt, i);
if (ivl_event_nany(event) > 0) if (ivl_event_nany(event) > 0)
return false; return false;
int npos = ivl_event_npos(event); int npos = ivl_event_npos(event);
for (int j = 0; j < npos; j++) for (int j = 0; j < npos; j++)
edge_triggered.insert(ivl_event_pos(event, j)); edge_triggered.insert(ivl_event_pos(event, j));
@ -804,13 +661,13 @@ static bool draw_synthesisable_wait(vhdl_process *proc, stmt_container *containe
edge = new vhdl_fcall("falling_edge", vhdl_type::boolean()); edge = new vhdl_fcall("falling_edge", vhdl_type::boolean());
} }
assert(edge); assert(edge);
edge->add_expr(nexus_to_var_ref(proc->get_scope(), *clock_net.begin())); edge->add_expr(nexus_to_var_ref(proc->get_scope(), *clock_net.begin()));
// Draw the clocked branch // Draw the clocked branch
// For an asynchronous reset we just want this around the else branch, // For an asynchronous reset we just want this around the else branch,
stmt_container *else_container = body->add_elsif(edge); stmt_container *else_container = body->add_elsif(edge);
draw_stmt(proc, else_container, ivl_stmt_cond_false(sub_stmt)); draw_stmt(proc, else_container, ivl_stmt_cond_false(sub_stmt));
if (proc->contains_wait_stmt()) { if (proc->contains_wait_stmt()) {
@ -850,7 +707,7 @@ static bool draw_synthesisable_wait(vhdl_process *proc, stmt_container *containe
* The difficulty stems from VHDL's restriction that a process with * The difficulty stems from VHDL's restriction that a process with
* a sensitivity list may not contain any `wait' statements: we need * a sensitivity list may not contain any `wait' statements: we need
* to generate these to accurately model some Verilog statements. * to generate these to accurately model some Verilog statements.
* *
* The steps followed are: * The steps followed are:
* 1) Determine whether this is the top-level statement in the process * 1) Determine whether this is the top-level statement in the process
* 2) If this is top-level, call draw_synthesisable_wait to see if the * 2) If this is top-level, call draw_synthesisable_wait to see if the
@ -886,20 +743,17 @@ static int draw_wait(vhdl_procedural *_proc, stmt_container *container,
// If this container is the top-level statement (i.e. it is the // If this container is the top-level statement (i.e. it is the
// first thing inside a process) then we can extract these // first thing inside a process) then we can extract these
// events out into the sensitivity list as long as we haven't // events out into the sensitivity list
// promoted any preceding assignments to initialisers bool is_top_level = container == proc->get_container()
bool is_top_level = && container->empty();
container == proc->get_container()
&& container->empty()
&& !proc->get_scope()->hoisted_initialiser();
// See if this can be implemented in a more idomatic way before we // See if this can be implemented in a more idiomatic way before we
// fall back on the generic translation // fall back on the generic translation
if (is_top_level && draw_synthesisable_wait(proc, container, stmt)) if (is_top_level && draw_synthesisable_wait(proc, container, stmt))
return 0; return 0;
int nevents = ivl_stmt_nevent(stmt); int nevents = ivl_stmt_nevent(stmt);
bool combinatorial = true; // True if no negedge/posedge events bool combinatorial = true; // True if no negedge/posedge events
for (int i = 0; i < nevents; i++) { for (int i = 0; i < nevents; i++) {
ivl_event_t event = ivl_stmt_events(stmt, i); ivl_event_t event = ivl_stmt_events(stmt, i);
@ -916,11 +770,11 @@ static int draw_wait(vhdl_procedural *_proc, stmt_container *container,
vhdl_wait_stmt *wait = NULL; vhdl_wait_stmt *wait = NULL;
if (proc->contains_wait_stmt() || !is_top_level) if (proc->contains_wait_stmt() || !is_top_level)
wait = new vhdl_wait_stmt(VHDL_WAIT_ON); wait = new vhdl_wait_stmt(VHDL_WAIT_ON);
for (int i = 0; i < nevents; i++) { for (int i = 0; i < nevents; i++) {
ivl_event_t event = ivl_stmt_events(stmt, i); ivl_event_t event = ivl_stmt_events(stmt, i);
int nany = ivl_event_nany(event); int nany = ivl_event_nany(event);
for (int j = 0; j < nany; j++) { for (int j = 0; j < nany; j++) {
ivl_nexus_t nexus = ivl_event_any(event, j); ivl_nexus_t nexus = ivl_event_any(event, j);
@ -949,22 +803,22 @@ static int draw_wait(vhdl_procedural *_proc, stmt_container *container,
stmt_container tmp_container; stmt_container tmp_container;
draw_stmt(proc, &tmp_container, ivl_stmt_sub_stmt(stmt), true); draw_stmt(proc, &tmp_container, ivl_stmt_sub_stmt(stmt), true);
for (int i = 0; i < nevents; i++) { for (int i = 0; i < nevents; i++) {
ivl_event_t event = ivl_stmt_events(stmt, i); ivl_event_t event = ivl_stmt_events(stmt, i);
int nany = ivl_event_nany(event); int nany = ivl_event_nany(event);
for (int j = 0; j < nany; j++) { for (int j = 0; j < nany; j++) {
ivl_nexus_t nexus = ivl_event_any(event, j); ivl_nexus_t nexus = ivl_event_any(event, j);
vhdl_var_ref *ref = nexus_to_var_ref(proc->get_scope(), nexus); vhdl_var_ref *ref = nexus_to_var_ref(proc->get_scope(), nexus);
ref->set_name(ref->get_name() + "'Event"); ref->set_name(ref->get_name() + "'Event");
test->add_expr(ref); test->add_expr(ref);
if (!proc->contains_wait_stmt() && is_top_level) if (!proc->contains_wait_stmt() && is_top_level)
proc->add_sensitivity(ref->get_name()); proc->add_sensitivity(ref->get_name());
} }
int nneg = ivl_event_nneg(event); int nneg = ivl_event_nneg(event);
for (int j = 0; j < nneg; j++) { for (int j = 0; j < nneg; j++) {
ivl_nexus_t nexus = ivl_event_neg(event, j); ivl_nexus_t nexus = ivl_event_neg(event, j);
@ -972,13 +826,13 @@ static int draw_wait(vhdl_procedural *_proc, stmt_container *container,
vhdl_fcall *detect = vhdl_fcall *detect =
new vhdl_fcall("falling_edge", vhdl_type::boolean()); new vhdl_fcall("falling_edge", vhdl_type::boolean());
detect->add_expr(ref); detect->add_expr(ref);
test->add_expr(detect); test->add_expr(detect);
if (!proc->contains_wait_stmt() && is_top_level) if (!proc->contains_wait_stmt() && is_top_level)
proc->add_sensitivity(ref->get_name()); proc->add_sensitivity(ref->get_name());
} }
int npos = ivl_event_npos(event); int npos = ivl_event_npos(event);
for (int j = 0; j < npos; j++) { for (int j = 0; j < npos; j++) {
ivl_nexus_t nexus = ivl_event_pos(event, j); ivl_nexus_t nexus = ivl_event_pos(event, j);
@ -986,14 +840,14 @@ static int draw_wait(vhdl_procedural *_proc, stmt_container *container,
vhdl_fcall *detect = vhdl_fcall *detect =
new vhdl_fcall("rising_edge", vhdl_type::boolean()); new vhdl_fcall("rising_edge", vhdl_type::boolean());
detect->add_expr(ref); detect->add_expr(ref);
test->add_expr(detect); test->add_expr(detect);
if (!proc->contains_wait_stmt() && is_top_level) if (!proc->contains_wait_stmt() && is_top_level)
proc->add_sensitivity(ref->get_name()); proc->add_sensitivity(ref->get_name());
} }
} }
if (proc->contains_wait_stmt() || !is_top_level) { if (proc->contains_wait_stmt() || !is_top_level) {
container->add_stmt(new vhdl_wait_stmt(VHDL_WAIT_UNTIL, test)); container->add_stmt(new vhdl_wait_stmt(VHDL_WAIT_UNTIL, test));
container->move_stmts_from(&tmp_container); container->move_stmts_from(&tmp_container);
@ -1009,9 +863,9 @@ static int draw_wait(vhdl_procedural *_proc, stmt_container *container,
container->add_stmt(edge_detect); container->add_stmt(edge_detect);
} }
} }
return 0; return 0;
} }
@ -1022,11 +876,8 @@ static int draw_if(vhdl_procedural *proc, stmt_container *container,
if (NULL == test) if (NULL == test)
return 1; return 1;
emit_wait_for_0(proc, container, stmt, test);
vhdl_if_stmt *vhdif = new vhdl_if_stmt(test); vhdl_if_stmt *vhdif = new vhdl_if_stmt(test);
container->add_stmt(vhdif);
ivl_statement_t cond_true_stmt = ivl_stmt_cond_true(stmt); ivl_statement_t cond_true_stmt = ivl_stmt_cond_true(stmt);
if (cond_true_stmt) if (cond_true_stmt)
draw_stmt(proc, vhdif->get_then_container(), cond_true_stmt, is_last); draw_stmt(proc, vhdif->get_then_container(), cond_true_stmt, is_last);
@ -1035,6 +886,8 @@ static int draw_if(vhdl_procedural *proc, stmt_container *container,
if (cond_false_stmt) if (cond_false_stmt)
draw_stmt(proc, vhdif->get_else_container(), cond_false_stmt, is_last); draw_stmt(proc, vhdif->get_else_container(), cond_false_stmt, is_last);
container->add_stmt(vhdif);
return 0; return 0;
} }
@ -1051,7 +904,7 @@ static vhdl_var_ref *draw_case_test(vhdl_procedural *proc, stmt_container *conta
if (typeid(*test) != typeid(vhdl_var_ref)) { if (typeid(*test) != typeid(vhdl_var_ref)) {
const char *tmp_name = "Verilog_Case_Ex"; const char *tmp_name = "Verilog_Case_Ex";
vhdl_type *test_type = new vhdl_type(*test->get_type()); vhdl_type *test_type = new vhdl_type(*test->get_type());
if (!proc->get_scope()->have_declared(tmp_name)) { if (!proc->get_scope()->have_declared(tmp_name)) {
proc->get_scope()->add_decl proc->get_scope()->add_decl
(new vhdl_var_decl(tmp_name, new vhdl_type(*test_type))); (new vhdl_var_decl(tmp_name, new vhdl_type(*test_type)));
@ -1072,7 +925,7 @@ static int draw_case(vhdl_procedural *proc, stmt_container *container,
vhdl_var_ref *test = draw_case_test(proc, container, stmt); vhdl_var_ref *test = draw_case_test(proc, container, stmt);
if (NULL == test) if (NULL == test)
return 1; return 1;
vhdl_case_stmt *vhdlcase = new vhdl_case_stmt(test); vhdl_case_stmt *vhdlcase = new vhdl_case_stmt(test);
container->add_stmt(vhdlcase); container->add_stmt(vhdlcase);
@ -1080,7 +933,7 @@ static int draw_case(vhdl_procedural *proc, stmt_container *container,
// possible case. So make sure we add an 'others' branch // possible case. So make sure we add an 'others' branch
// if there isn't a default one. // if there isn't a default one.
bool have_others = false; bool have_others = false;
int nbranches = ivl_stmt_case_count(stmt); int nbranches = ivl_stmt_case_count(stmt);
for (int i = 0; i < nbranches; i++) { for (int i = 0; i < nbranches; i++) {
vhdl_expr *when; vhdl_expr *when;
@ -1094,7 +947,7 @@ static int draw_case(vhdl_procedural *proc, stmt_container *container,
when = new vhdl_var_ref("others", NULL); when = new vhdl_var_ref("others", NULL);
have_others = true; have_others = true;
} }
vhdl_case_branch *branch = new vhdl_case_branch(when); vhdl_case_branch *branch = new vhdl_case_branch(when);
vhdlcase->add_branch(branch); vhdlcase->add_branch(branch);
@ -1107,8 +960,8 @@ static int draw_case(vhdl_procedural *proc, stmt_container *container,
new vhdl_case_branch(new vhdl_var_ref("others", NULL)); new vhdl_case_branch(new vhdl_var_ref("others", NULL));
others->get_container()->add_stmt(new vhdl_null_stmt()); others->get_container()->add_stmt(new vhdl_null_stmt());
vhdlcase->add_branch(others); vhdlcase->add_branch(others);
} }
return 0; return 0;
} }
@ -1472,12 +1325,12 @@ int draw_casezx(vhdl_procedural *proc, stmt_container *container,
return 1; return 1;
vhdl_if_stmt *result = NULL; vhdl_if_stmt *result = NULL;
int nbranches = ivl_stmt_case_count(stmt); int nbranches = ivl_stmt_case_count(stmt);
bool is_casez = ivl_statement_type(stmt) == IVL_ST_CASEZ; bool is_casez = ivl_statement_type(stmt) == IVL_ST_CASEZ;
for (int i = 0; i < nbranches; i++) { for (int i = 0; i < nbranches; i++) {
stmt_container *where = NULL; stmt_container *where = NULL;
ivl_expr_t net = ivl_stmt_case_expr(stmt, i); ivl_expr_t net = ivl_stmt_case_expr(stmt, i);
if (net) { if (net) {
vhdl_binop_expr *all = vhdl_binop_expr *all =
@ -1524,7 +1377,7 @@ int draw_casezx(vhdl_procedural *proc, stmt_container *container,
// We don't actually use the generated `test' expression // We don't actually use the generated `test' expression
delete test; delete test;
return 0; return 0;
} }
@ -1540,7 +1393,7 @@ int draw_while(vhdl_procedural *proc, stmt_container *container,
int rc = draw_stmt(proc, &tmp_container, ivl_stmt_sub_stmt(stmt)); int rc = draw_stmt(proc, &tmp_container, ivl_stmt_sub_stmt(stmt));
if (rc != 0) if (rc != 0)
return 1; return 1;
vhdl_expr *test = translate_expr(ivl_stmt_cond_expr(stmt)); vhdl_expr *test = translate_expr(ivl_stmt_cond_expr(stmt));
if (NULL == test) if (NULL == test)
return 1; return 1;
@ -1550,13 +1403,9 @@ int draw_while(vhdl_procedural *proc, stmt_container *container,
vhdl_type boolean(VHDL_TYPE_BOOLEAN); vhdl_type boolean(VHDL_TYPE_BOOLEAN);
test = test->cast(&boolean); test = test->cast(&boolean);
emit_wait_for_0(proc, container, stmt, test);
vhdl_while_stmt *loop = new vhdl_while_stmt(test); vhdl_while_stmt *loop = new vhdl_while_stmt(test);
draw_stmt(proc, loop->get_container(), ivl_stmt_sub_stmt(stmt)); draw_stmt(proc, loop->get_container(), ivl_stmt_sub_stmt(stmt));
emit_wait_for_0(proc, loop->get_container(), stmt, test);
container->add_stmt(loop); container->add_stmt(loop);
return 0; return 0;
} }
@ -1588,7 +1437,7 @@ int draw_repeat(vhdl_procedural *proc, stmt_container *container,
container->add_stmt(loop); container->add_stmt(loop);
draw_stmt(proc, loop->get_container(), ivl_stmt_sub_stmt(stmt)); draw_stmt(proc, loop->get_container(), ivl_stmt_sub_stmt(stmt));
return 0; return 0;
} }
@ -1606,7 +1455,7 @@ int draw_utask(vhdl_procedural *proc, stmt_container *container,
// TOOD: this completely ignores parameters! // TOOD: this completely ignores parameters!
draw_stmt(proc, container, ivl_scope_def(tscope), false); draw_stmt(proc, container, ivl_scope_def(tscope), false);
return 0; return 0;
} }
@ -1624,7 +1473,7 @@ int draw_stmt(vhdl_procedural *proc, stmt_container *container,
ivl_statement_t stmt, bool is_last) ivl_statement_t stmt, bool is_last)
{ {
assert(stmt); assert(stmt);
switch (ivl_statement_type(stmt)) { switch (ivl_statement_type(stmt)) {
case IVL_ST_STASK: case IVL_ST_STASK:
return draw_stask(proc, container, stmt); return draw_stask(proc, container, stmt);
@ -1674,6 +1523,6 @@ int draw_stmt(vhdl_procedural *proc, stmt_container *container,
error("No VHDL translation for statement at %s:%d (type = %d)", error("No VHDL translation for statement at %s:%d (type = %d)",
ivl_stmt_file(stmt), ivl_stmt_lineno(stmt), ivl_stmt_file(stmt), ivl_stmt_lineno(stmt),
ivl_statement_type(stmt)); ivl_statement_type(stmt));
return 1; return 1;
} }
} }

View File

@ -92,7 +92,7 @@ void support_function::emit_reduction(std::ostream &of, int level,
// Emit a VHDL function emulating a Verilog reduction operator // Emit a VHDL function emulating a Verilog reduction operator
// Where op is the corresponding VHDL operator and unit is the // Where op is the corresponding VHDL operator and unit is the
// right-unit of the operator // right-unit of the operator
of << "(X : std_logic_vector) return std_logic is" of << "(X : std_logic_vector) return std_logic is"
<< nl_string(indent(level)) << nl_string(indent(level))
<< "variable R : std_logic := '" << unit << "';" << nl_string(level) << "variable R : std_logic := '" << unit << "';" << nl_string(level)
@ -106,7 +106,7 @@ void support_function::emit_reduction(std::ostream &of, int level,
void support_function::emit(std::ostream &of, int level) const void support_function::emit(std::ostream &of, int level) const
{ {
of << nl_string(level) << "function " << function_name(type_); of << nl_string(level) << "function " << function_name(type_);
switch (type_) { switch (type_) {
case SF_UNSIGNED_TO_BOOLEAN: case SF_UNSIGNED_TO_BOOLEAN:
of << "(X : unsigned) return Boolean is" << nl_string(level) of << "(X : unsigned) return Boolean is" << nl_string(level)
@ -169,6 +169,6 @@ void support_function::emit(std::ostream &of, int level) const
default: default:
assert(false); assert(false);
} }
of << nl_string(level) << "end function;"; of << nl_string(level) << "end function;";
} }

View File

@ -52,7 +52,7 @@ private:
void emit_ternary(std::ostream &of, int level) const; void emit_ternary(std::ostream &of, int level) const;
void emit_reduction(std::ostream &of, int level, const char *op, void emit_reduction(std::ostream &of, int level, const char *op,
char unit) const; char unit) const;
support_function_t type_; support_function_t type_;
}; };

View File

@ -80,7 +80,7 @@ void debug_msg(const char *fmt, ...)
va_start(args, fmt); va_start(args, fmt);
if (std::strcmp(ivl_design_flag(g_design, "debug"), "")) { if (std::strcmp(ivl_design_flag(g_design, "debug"), "")) {
std::fputs("[DEBUG] ", stdout); std::fputs("[DEBUG] ", stdout);
std::vprintf(fmt, args); std::vprintf(fmt, args);
std::putchar('\n'); std::putchar('\n');
} }
@ -127,10 +127,10 @@ extern "C" int target_design(ivl_design_t des)
emit_all_entities(outfile, max_depth); emit_all_entities(outfile, max_depth);
} }
// Clean up // Clean up
free_all_vhdl_objects(); free_all_vhdl_objects();
return g_errors; return g_errors;
} }

View File

@ -40,7 +40,7 @@ std::string nl_string(int level)
{ {
std::ostringstream ss; std::ostringstream ss;
newline(ss, level); newline(ss, level);
return ss.str(); return ss.str();
} }
/* /*
@ -81,21 +81,10 @@ void vhdl_element::emit_comment(std::ostream &of, int level,
{ {
if (comment_.size() > 0) { if (comment_.size() > 0) {
if (end_of_line) if (end_of_line)
of << " -- " << comment_; of << " ";
else { of << "-- " << comment_;
// Comment may contain embedded newlines if (!end_of_line)
of << "-- ";
for (string::const_iterator it = comment_.begin();
it != comment_.end(); ++it) {
if (*it == '\n') {
newline(of, level);
of << "-- ";
}
else
of << *it;
}
newline(of, level); newline(of, level);
}
} }
} }
@ -109,7 +98,7 @@ void vhdl_element::print() const
// This records the pointer allocated in a static field of vhdl_element // This records the pointer allocated in a static field of vhdl_element
// so we can delete it just before the code generator exits. // so we can delete it just before the code generator exits.
void* vhdl_element::operator new(size_t size) throw (bad_alloc) void* vhdl_element::operator new(size_t size) throw (bad_alloc)
{ {
// Let the default new handle the allocation // Let the default new handle the allocation
void* ptr = ::operator new(size); void* ptr = ::operator new(size);
@ -126,7 +115,7 @@ void* vhdl_element::operator new(size_t size) throw (bad_alloc)
// This just sets the corresponding pointer in vhdl_element::allocated_ // This just sets the corresponding pointer in vhdl_element::allocated_
// to NULL (since it's safe to delete a NULL pointer). // to NULL (since it's safe to delete a NULL pointer).
void vhdl_element::operator delete(void* ptr) void vhdl_element::operator delete(void* ptr)
{ {
// Let the default delete handle the deallocation // Let the default delete handle the deallocation
::operator delete(ptr); ::operator delete(ptr);

View File

@ -48,7 +48,7 @@ public:
void* operator new(size_t size) throw (std::bad_alloc); void* operator new(size_t size) throw (std::bad_alloc);
void operator delete(void* ptr); void operator delete(void* ptr);
virtual void emit(std::ostream &of, int level=0) const = 0; virtual void emit(std::ostream &of, int level=0) const = 0;
void print() const; void print() const;

View File

@ -29,8 +29,8 @@ template <class T>
void emit_children(std::ostream &of, void emit_children(std::ostream &of,
const std::list<T*> &children, const std::list<T*> &children,
int level, const char *delim = "", int level, const char *delim = "",
bool trailing_newline = true) bool trailing_newline = true)
{ {
// Don't indent if there are no children // Don't indent if there are no children
if (children.empty()) if (children.empty())
newline(of, level); newline(of, level);

View File

@ -1,7 +1,7 @@
/* /*
* VHDL abstract syntax elements. * VHDL abstract syntax elements.
* *
* Copyright (C) 2008-2010 Nick Gasson (nick@nickg.me.uk) * Copyright (C) 2008 Nick Gasson (nick@nickg.me.uk)
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -31,15 +31,14 @@
using namespace std; using namespace std;
vhdl_scope::vhdl_scope() vhdl_scope::vhdl_scope()
: parent_(NULL), init_(false), sig_assign_(true), : parent_(NULL), init_(false), sig_assign_(true)
hoisted_init_(false)
{ {
} }
vhdl_scope::~vhdl_scope() vhdl_scope::~vhdl_scope()
{ {
} }
void vhdl_scope::set_initializing(bool i) void vhdl_scope::set_initializing(bool i)
@ -101,16 +100,6 @@ vhdl_scope *vhdl_scope::get_parent() const
return parent_; return parent_;
} }
bool vhdl_scope::hoisted_initialiser() const
{
return hoisted_init_;
}
void vhdl_scope::hoisted_initialiser(bool h)
{
hoisted_init_ = h;
}
vhdl_entity::vhdl_entity(const string& name, vhdl_arch *arch, int depth__) vhdl_entity::vhdl_entity(const string& name, vhdl_arch *arch, int depth__)
: depth(depth__), name_(name), arch_(arch), : depth(depth__), name_(name), arch_(arch),
time_unit_(TIME_UNIT_NS) time_unit_(TIME_UNIT_NS)
@ -120,7 +109,7 @@ vhdl_entity::vhdl_entity(const string& name, vhdl_arch *arch, int depth__)
vhdl_entity::~vhdl_entity() vhdl_entity::~vhdl_entity()
{ {
} }
void vhdl_entity::add_port(vhdl_port_decl *decl) void vhdl_entity::add_port(vhdl_port_decl *decl)
@ -135,8 +124,9 @@ void vhdl_entity::emit(std::ostream &of, int level) const
of << "library ieee;" << std::endl; of << "library ieee;" << std::endl;
of << "use ieee.std_logic_1164.all;" << std::endl; of << "use ieee.std_logic_1164.all;" << std::endl;
of << "use ieee.numeric_std.all;" << std::endl; of << "use ieee.numeric_std.all;" << std::endl;
of << "use std.textio.all;" << std::endl;
of << std::endl; of << std::endl;
emit_comment(of, level); emit_comment(of, level);
of << "entity " << name_ << " is"; of << "entity " << name_ << " is";
@ -146,7 +136,7 @@ void vhdl_entity::emit(std::ostream &of, int level) const
emit_children<vhdl_decl>(of, ports_.get_decls(), indent(level), ";"); emit_children<vhdl_decl>(of, ports_.get_decls(), indent(level), ";");
of << ");"; of << ");";
} }
newline(of, level); newline(of, level);
of << "end entity; "; of << "end entity; ";
blank_line(of, level); // Extra blank line after entities blank_line(of, level); // Extra blank line after entities
@ -164,7 +154,7 @@ vhdl_const_time* scale_time(const vhdl_entity* ent, uint64_t t)
void vhdl_entity::set_time_units(int units, int precision) void vhdl_entity::set_time_units(int units, int precision)
{ {
int vhdl_units = std::min(units, precision); int vhdl_units = std::min(units, precision);
if (vhdl_units >= -3) if (vhdl_units >= -3)
time_unit_ = TIME_UNIT_MS; time_unit_ = TIME_UNIT_MS;
else if (vhdl_units >= -6) else if (vhdl_units >= -6)
@ -177,7 +167,7 @@ void vhdl_entity::set_time_units(int units, int precision)
vhdl_arch::~vhdl_arch() vhdl_arch::~vhdl_arch()
{ {
} }
void vhdl_arch::add_stmt(vhdl_process *proc) void vhdl_arch::add_stmt(vhdl_process *proc)
@ -203,16 +193,6 @@ void vhdl_arch::emit(std::ostream &of, int level) const
blank_line(of, level); // Extra blank line after architectures; blank_line(of, level); // Extra blank line after architectures;
} }
void vhdl_procedural::add_blocking_target(vhdl_var_ref* ref)
{
blocking_targets_.insert(ref->get_name());
}
bool vhdl_procedural::is_blocking_target(vhdl_var_ref* ref) const
{
return blocking_targets_.find(ref->get_name()) != blocking_targets_.end();
}
void vhdl_process::add_sensitivity(const std::string &name) void vhdl_process::add_sensitivity(const std::string &name)
{ {
sens_.push_back(name); sens_.push_back(name);
@ -233,7 +213,7 @@ void vhdl_process::emit(std::ostream &of, int level) const
if (name_.size() > 0) if (name_.size() > 0)
of << name_ << ": "; of << name_ << ": ";
of << "process "; of << "process ";
int num_sens = sens_.size(); int num_sens = sens_.size();
if (num_sens > 0) { if (num_sens > 0) {
of << "("; of << "(";
@ -255,7 +235,7 @@ void vhdl_process::emit(std::ostream &of, int level) const
stmt_container::~stmt_container() stmt_container::~stmt_container()
{ {
} }
void stmt_container::add_stmt(vhdl_seq_stmt *stmt) void stmt_container::add_stmt(vhdl_seq_stmt *stmt)
@ -288,18 +268,18 @@ void stmt_container::find_vars(vhdl_var_set_t& read,
void stmt_container::emit(std::ostream &of, int level, bool newline) const void stmt_container::emit(std::ostream &of, int level, bool newline) const
{ {
emit_children<vhdl_seq_stmt>(of, stmts_, level, "", newline); emit_children<vhdl_seq_stmt>(of, stmts_, level, "", newline);
} }
vhdl_comp_inst::vhdl_comp_inst(const char *inst_name, const char *comp_name) vhdl_comp_inst::vhdl_comp_inst(const char *inst_name, const char *comp_name)
: comp_name_(comp_name), inst_name_(inst_name) : comp_name_(comp_name), inst_name_(inst_name)
{ {
} }
vhdl_comp_inst::~vhdl_comp_inst() vhdl_comp_inst::~vhdl_comp_inst()
{ {
} }
void vhdl_comp_inst::map_port(const string& name, vhdl_expr *expr) void vhdl_comp_inst::map_port(const string& name, vhdl_expr *expr)
@ -331,7 +311,7 @@ void vhdl_comp_inst::emit(std::ostream &of, int level) const
newline(of, indent(level)); newline(of, indent(level));
of << ")"; of << ")";
} }
of << ";"; of << ";";
} }
@ -352,7 +332,7 @@ vhdl_component_decl *vhdl_component_decl::component_decl_for(vhdl_entity *ent)
(ent->get_name().c_str()); (ent->get_name().c_str());
decl->ports_ = ent->get_scope()->get_decls(); decl->ports_ = ent->get_scope()->get_decls();
return decl; return decl;
} }
@ -368,14 +348,14 @@ void vhdl_component_decl::emit(std::ostream &of, int level) const
emit_children<vhdl_decl>(of, ports_, indent(level), ";"); emit_children<vhdl_decl>(of, ports_, indent(level), ";");
of << ");"; of << ");";
} }
newline(of, level); newline(of, level);
of << "end component;"; of << "end component;";
} }
vhdl_wait_stmt::~vhdl_wait_stmt() vhdl_wait_stmt::~vhdl_wait_stmt()
{ {
} }
void vhdl_wait_stmt::find_vars(vhdl_var_set_t& read, void vhdl_wait_stmt::find_vars(vhdl_var_set_t& read,
@ -417,14 +397,13 @@ void vhdl_wait_stmt::emit(std::ostream &of, int level) const
} }
break; break;
} }
of << ";"; of << ";";
emit_comment(of, level, true);
} }
vhdl_decl::~vhdl_decl() vhdl_decl::~vhdl_decl()
{ {
} }
// Make a reference object to this declaration // Make a reference object to this declaration
@ -440,7 +419,7 @@ const vhdl_type *vhdl_decl::get_type() const
} }
void vhdl_decl::set_initial(vhdl_expr *initial) void vhdl_decl::set_initial(vhdl_expr *initial)
{ {
if (!has_initial_) { if (!has_initial_) {
assert(initial_ == NULL); assert(initial_ == NULL);
initial_ = initial; initial_ = initial;
@ -451,7 +430,7 @@ void vhdl_decl::set_initial(vhdl_expr *initial)
void vhdl_port_decl::emit(std::ostream &of, int level) const void vhdl_port_decl::emit(std::ostream &of, int level) const
{ {
of << name_ << " : "; of << name_ << " : ";
switch (mode_) { switch (mode_) {
case VHDL_PORT_IN: case VHDL_PORT_IN:
of << "in "; of << "in ";
@ -466,7 +445,7 @@ void vhdl_port_decl::emit(std::ostream &of, int level) const
of << "buffer "; of << "buffer ";
break; break;
} }
type_->emit(of, level); type_->emit(of, level);
} }
@ -490,12 +469,12 @@ void vhdl_var_decl::emit(std::ostream &of, int level) const
{ {
of << "variable " << name_ << " : "; of << "variable " << name_ << " : ";
type_->emit(of, level); type_->emit(of, level);
if (initial_) { if (initial_) {
of << " := "; of << " := ";
initial_->emit(of, level); initial_->emit(of, level);
} }
of << ";"; of << ";";
emit_comment(of, level, true); emit_comment(of, level, true);
} }
@ -504,12 +483,12 @@ void vhdl_signal_decl::emit(std::ostream &of, int level) const
{ {
of << "signal " << name_ << " : "; of << "signal " << name_ << " : ";
type_->emit(of, level); type_->emit(of, level);
if (initial_) { if (initial_) {
of << " := "; of << " := ";
initial_->emit(of, level); initial_->emit(of, level);
} }
of << ";"; of << ";";
emit_comment(of, level, true); emit_comment(of, level, true);
} }
@ -523,7 +502,7 @@ void vhdl_type_decl::emit(std::ostream &of, int level) const
vhdl_expr::~vhdl_expr() vhdl_expr::~vhdl_expr()
{ {
} }
void vhdl_expr_list::add_expr(vhdl_expr *e) void vhdl_expr_list::add_expr(vhdl_expr *e)
@ -533,7 +512,7 @@ void vhdl_expr_list::add_expr(vhdl_expr *e)
vhdl_expr_list::~vhdl_expr_list() vhdl_expr_list::~vhdl_expr_list()
{ {
} }
void vhdl_expr_list::find_vars(vhdl_var_set_t& read) void vhdl_expr_list::find_vars(vhdl_var_set_t& read)
@ -546,7 +525,7 @@ void vhdl_expr_list::find_vars(vhdl_var_set_t& read)
void vhdl_expr_list::emit(std::ostream &of, int level) const void vhdl_expr_list::emit(std::ostream &of, int level) const
{ {
of << "("; of << "(";
int size = exprs_.size(); int size = exprs_.size();
std::list<vhdl_expr*>::const_iterator it; std::list<vhdl_expr*>::const_iterator it;
for (it = exprs_.begin(); it != exprs_.end(); ++it) { for (it = exprs_.begin(); it != exprs_.end(); ++it) {
@ -574,7 +553,7 @@ void vhdl_pcall_stmt::find_vars(vhdl_var_set_t& read,
vhdl_var_ref::~vhdl_var_ref() vhdl_var_ref::~vhdl_var_ref()
{ {
} }
void vhdl_var_ref::set_slice(vhdl_expr *s, int w) void vhdl_var_ref::set_slice(vhdl_expr *s, int w)
@ -583,18 +562,18 @@ void vhdl_var_ref::set_slice(vhdl_expr *s, int w)
slice_ = s; slice_ = s;
slice_width_ = w; slice_width_ = w;
vhdl_type_name_t tname = type_->get_name(); vhdl_type_name_t tname = type_->get_name();
if (tname == VHDL_TYPE_ARRAY) { if (tname == VHDL_TYPE_ARRAY) {
type_ = type_->get_base(); type_ = type_->get_base();
} }
else { else {
assert(tname == VHDL_TYPE_UNSIGNED || tname == VHDL_TYPE_SIGNED); assert(tname == VHDL_TYPE_UNSIGNED || tname == VHDL_TYPE_SIGNED);
if (w > 0) if (w > 0)
type_ = new vhdl_type(tname, w); type_ = new vhdl_type(tname, w);
else else
type_ = vhdl_type::std_logic(); type_ = vhdl_type::std_logic();
} }
} }
@ -619,7 +598,11 @@ void vhdl_var_ref::emit(std::ostream &of, int level) const
void vhdl_const_string::emit(std::ostream &of, int level) const void vhdl_const_string::emit(std::ostream &of, int level) const
{ {
of << "\"" << value_ << "\""; // In some instances a string literal can be ambiguous between
// a String type and some other types (e.g. std_logic_vector)
// The explicit cast to String removes this ambiguity (although
// isn't always strictly necessary)
of << "String'(\"" << value_ << "\")";
} }
void vhdl_null_stmt::emit(std::ostream &of, int level) const void vhdl_null_stmt::emit(std::ostream &of, int level) const
@ -641,13 +624,13 @@ void vhdl_fcall::emit(std::ostream &of, int level) const
vhdl_abstract_assign_stmt::~vhdl_abstract_assign_stmt() vhdl_abstract_assign_stmt::~vhdl_abstract_assign_stmt()
{ {
} }
void vhdl_abstract_assign_stmt::find_vars(vhdl_var_set_t& read, void vhdl_abstract_assign_stmt::find_vars(vhdl_var_set_t& read,
vhdl_var_set_t& write) vhdl_var_set_t& write)
{ {
lhs_->find_vars(write); write.insert(lhs_);
rhs_->find_vars(read); rhs_->find_vars(read);
} }
@ -661,7 +644,7 @@ void vhdl_nbassign_stmt::emit(std::ostream &of, int level) const
of << " after "; of << " after ";
after_->emit(of, level); after_->emit(of, level);
} }
of << ";"; of << ";";
} }
@ -674,12 +657,12 @@ void vhdl_assign_stmt::emit(std::ostream &of, int level) const
} }
vhdl_const_bits::vhdl_const_bits(const char *value, int width, bool issigned, vhdl_const_bits::vhdl_const_bits(const char *value, int width, bool issigned,
bool qualify) bool qualify)
: vhdl_expr(issigned ? vhdl_type::nsigned(width) : vhdl_expr(issigned ? vhdl_type::nsigned(width)
: vhdl_type::nunsigned(width), true), : vhdl_type::nunsigned(width), true),
qualified_(qualify), qualified_(qualify),
signed_(issigned) signed_(issigned)
{ {
// Can't rely on value being NULL-terminated // Can't rely on value being NULL-terminated
while (width--) while (width--)
value_.push_back(*value++); value_.push_back(*value++);
@ -709,9 +692,9 @@ void vhdl_const_bits::emit(std::ostream &of, int level) const
&& !has_meta_bits() && bits <= 64 && bits % 4 == 0) { && !has_meta_bits() && bits <= 64 && bits % 4 == 0) {
of << "X\"" << hex << setfill('0') << setw(bits / 4) << ival; of << "X\"" << hex << setfill('0') << setw(bits / 4) << ival;
} }
else { else {
of << "\""; of << "\"";
std::string::const_reverse_iterator it; std::string::const_reverse_iterator it;
for (it = value_.rbegin(); it != value_.rend(); ++it) for (it = value_.rbegin(); it != value_.rend(); ++it)
of << vl_to_vhdl_bit(*it); of << vl_to_vhdl_bit(*it);
@ -749,7 +732,7 @@ void vhdl_const_time::emit(std::ostream &of, int level) const
vhdl_cassign_stmt::~vhdl_cassign_stmt() vhdl_cassign_stmt::~vhdl_cassign_stmt()
{ {
} }
void vhdl_cassign_stmt::add_condition(vhdl_expr *value, vhdl_expr *cond) void vhdl_cassign_stmt::add_condition(vhdl_expr *value, vhdl_expr *cond)
@ -774,51 +757,19 @@ void vhdl_cassign_stmt::emit(std::ostream &of, int level) const
of << "else "; of << "else ";
} }
rhs_->emit(of, level); rhs_->emit(of, level);
if (after_) { if (after_) {
of << " after "; of << " after ";
after_->emit(of, level); after_->emit(of, level);
} }
of << ";"; of << ";";
} }
vhdl_report_stmt::vhdl_report_stmt(vhdl_expr *text,
vhdl_severity_t severity)
: severity_(severity),
text_(text)
{
}
void vhdl_report_stmt::emit(ostream& of, int level) const
{
of << "report ";
text_->emit(of, level);
if (severity_ != SEVERITY_NOTE) {
const char *levels[] = { "note", "warning", "error", "failure" };
of << " severity " << levels[severity_];
}
of << ";";
}
void vhdl_report_stmt::find_vars(vhdl_var_set_t& read, vhdl_var_set_t& write)
{
text_->find_vars(read);
}
vhdl_assert_stmt::vhdl_assert_stmt(const char *reason)
: vhdl_report_stmt(new vhdl_const_string(reason), SEVERITY_FAILURE)
{
}
void vhdl_assert_stmt::emit(std::ostream &of, int level) const void vhdl_assert_stmt::emit(std::ostream &of, int level) const
{ {
of << "assert false "; // TODO: Allow arbitrary expression of << "assert false"; // TODO: Allow arbitrary expression
vhdl_report_stmt::emit(of, level); of << " report \"" << reason_ << "\" severity failure;";
} }
vhdl_if_stmt::vhdl_if_stmt(vhdl_expr *test) vhdl_if_stmt::vhdl_if_stmt(vhdl_expr *test)
@ -830,7 +781,7 @@ vhdl_if_stmt::vhdl_if_stmt(vhdl_expr *test)
vhdl_if_stmt::~vhdl_if_stmt() vhdl_if_stmt::~vhdl_if_stmt()
{ {
} }
stmt_container *vhdl_if_stmt::add_elsif(vhdl_expr *test) stmt_container *vhdl_if_stmt::add_elsif(vhdl_expr *test)
@ -843,7 +794,7 @@ stmt_container *vhdl_if_stmt::add_elsif(vhdl_expr *test)
void vhdl_if_stmt::emit(std::ostream &of, int level) const void vhdl_if_stmt::emit(std::ostream &of, int level) const
{ {
emit_comment(of, level); emit_comment(of, level);
of << "if "; of << "if ";
test_->emit(of, level); test_->emit(of, level);
of << " then"; of << " then";
@ -856,7 +807,7 @@ void vhdl_if_stmt::emit(std::ostream &of, int level) const
of << " then"; of << " then";
(*it).container->emit(of, level); (*it).container->emit(of, level);
} }
if (!else_part_.empty()) { if (!else_part_.empty()) {
of << "else"; of << "else";
else_part_.emit(of, level); else_part_.emit(of, level);
@ -897,7 +848,7 @@ void vhdl_expr::close_parens(std::ostream& of)
vhdl_unaryop_expr::~vhdl_unaryop_expr() vhdl_unaryop_expr::~vhdl_unaryop_expr()
{ {
} }
void vhdl_unaryop_expr::find_vars(vhdl_var_set_t& read) void vhdl_unaryop_expr::find_vars(vhdl_var_set_t& read)
@ -932,7 +883,7 @@ vhdl_binop_expr::vhdl_binop_expr(vhdl_expr *left, vhdl_binop_t op,
vhdl_binop_expr::~vhdl_binop_expr() vhdl_binop_expr::~vhdl_binop_expr()
{ {
} }
void vhdl_binop_expr::add_expr(vhdl_expr *e) void vhdl_binop_expr::add_expr(vhdl_expr *e)
@ -951,7 +902,7 @@ void vhdl_binop_expr::emit(std::ostream &of, int level) const
{ {
open_parens(of); open_parens(of);
assert(operands_.size() > 0); assert(operands_.size() > 0);
std::list<vhdl_expr*>::const_iterator it = operands_.begin(); std::list<vhdl_expr*>::const_iterator it = operands_.begin();
(*it)->emit(of, level); (*it)->emit(of, level);
@ -965,14 +916,14 @@ void vhdl_binop_expr::emit(std::ostream &of, int level) const
of << " " << ops[op_] << " "; of << " " << ops[op_] << " ";
(*it)->emit(of, level); (*it)->emit(of, level);
} }
close_parens(of); close_parens(of);
} }
vhdl_bit_spec_expr::~vhdl_bit_spec_expr() vhdl_bit_spec_expr::~vhdl_bit_spec_expr()
{ {
} }
void vhdl_bit_spec_expr::add_bit(int bit, vhdl_expr *e) void vhdl_bit_spec_expr::add_bit(int bit, vhdl_expr *e)
@ -984,7 +935,7 @@ void vhdl_bit_spec_expr::add_bit(int bit, vhdl_expr *e)
void vhdl_bit_spec_expr::emit(std::ostream &of, int level) const void vhdl_bit_spec_expr::emit(std::ostream &of, int level) const
{ {
of << "("; of << "(";
std::list<bit_map>::const_iterator it; std::list<bit_map>::const_iterator it;
it = bits_.begin(); it = bits_.begin();
while (it != bits_.end()) { while (it != bits_.end()) {
@ -998,13 +949,13 @@ void vhdl_bit_spec_expr::emit(std::ostream &of, int level) const
of << (bits_.empty() ? "" : ", ") << "others => "; of << (bits_.empty() ? "" : ", ") << "others => ";
others_->emit(of, level); others_->emit(of, level);
} }
of << ")"; of << ")";
} }
vhdl_case_branch::~vhdl_case_branch() vhdl_case_branch::~vhdl_case_branch()
{ {
} }
void vhdl_case_branch::emit(std::ostream &of, int level) const void vhdl_case_branch::emit(std::ostream &of, int level) const
@ -1017,7 +968,7 @@ void vhdl_case_branch::emit(std::ostream &of, int level) const
vhdl_case_stmt::~vhdl_case_stmt() vhdl_case_stmt::~vhdl_case_stmt()
{ {
} }
void vhdl_case_stmt::find_vars(vhdl_var_set_t& read, void vhdl_case_stmt::find_vars(vhdl_var_set_t& read,
@ -1048,13 +999,13 @@ void vhdl_case_stmt::emit(std::ostream &of, int level) const
else else
newline(of, level); newline(of, level);
} }
of << "end case;"; of << "end case;";
} }
vhdl_while_stmt::~vhdl_while_stmt() vhdl_while_stmt::~vhdl_while_stmt()
{ {
} }
void vhdl_while_stmt::find_vars(vhdl_var_set_t& read, void vhdl_while_stmt::find_vars(vhdl_var_set_t& read,
@ -1088,7 +1039,7 @@ void vhdl_loop_stmt::emit(std::ostream &of, int level) const
vhdl_for_stmt::~vhdl_for_stmt() vhdl_for_stmt::~vhdl_for_stmt()
{ {
} }
@ -1156,7 +1107,7 @@ void vhdl_param_decl::emit(std::ostream &of, int level) const
vhdl_with_select_stmt::~vhdl_with_select_stmt() vhdl_with_select_stmt::~vhdl_with_select_stmt()
{ {
} }
void vhdl_with_select_stmt::emit(std::ostream &of, int level) const void vhdl_with_select_stmt::emit(std::ostream &of, int level) const
@ -1164,12 +1115,12 @@ void vhdl_with_select_stmt::emit(std::ostream &of, int level) const
of << "with "; of << "with ";
test_->emit(of, level); test_->emit(of, level);
of << " select"; of << " select";
emit_comment(of, level, true); emit_comment(of, level, true);
newline(of, indent(level)); newline(of, indent(level));
out_->emit(of, level); out_->emit(of, level);
of << " <= "; of << " <= ";
when_list_t::const_iterator it = whens_.begin(); when_list_t::const_iterator it = whens_.begin();
while (it != whens_.end()) { while (it != whens_.end()) {
(*it).value->emit(of, level); (*it).value->emit(of, level);
@ -1179,7 +1130,7 @@ void vhdl_with_select_stmt::emit(std::ostream &of, int level) const
} }
of << " when "; of << " when ";
(*it).cond->emit(of, level); (*it).cond->emit(of, level);
if (++it != whens_.end() || others_ != NULL) { if (++it != whens_.end() || others_ != NULL) {
of << ","; of << ",";
newline(of, indent(level)); newline(of, indent(level));

View File

@ -44,7 +44,7 @@ public:
const vhdl_type *get_type() const { return type_; } const vhdl_type *get_type() const { return type_; }
bool constant() const { return isconst_; } bool constant() const { return isconst_; }
vhdl_expr *cast(const vhdl_type *to); vhdl_expr *cast(const vhdl_type *to);
virtual vhdl_expr *resize(int newwidth); virtual vhdl_expr *resize(int newwidth);
virtual vhdl_expr *to_boolean(); virtual vhdl_expr *to_boolean();
@ -52,8 +52,7 @@ public:
virtual vhdl_expr *to_std_logic(); virtual vhdl_expr *to_std_logic();
virtual vhdl_expr *to_std_ulogic(); virtual vhdl_expr *to_std_ulogic();
virtual vhdl_expr *to_vector(vhdl_type_name_t name, int w); virtual vhdl_expr *to_vector(vhdl_type_name_t name, int w);
virtual vhdl_expr *to_string(); virtual void find_vars(vhdl_var_set_t& read) const {}
virtual void find_vars(vhdl_var_set_t& read) {}
protected: protected:
static void open_parens(ostream& of); static void open_parens(ostream& of);
@ -74,7 +73,7 @@ public:
vhdl_expr *slice = NULL) vhdl_expr *slice = NULL)
: vhdl_expr(type), name_(name), slice_(slice), slice_width_(0) {} : vhdl_expr(type), name_(name), slice_(slice), slice_width_(0) {}
~vhdl_var_ref(); ~vhdl_var_ref();
void emit(std::ostream &of, int level) const; void emit(std::ostream &of, int level) const;
const std::string &get_name() const { return name_; } const std::string &get_name() const { return name_; }
void set_name(const std::string &name) { name_ = name; } void set_name(const std::string &name) { name_ = name; }
@ -177,7 +176,7 @@ private:
class vhdl_const_string : public vhdl_expr { class vhdl_const_string : public vhdl_expr {
public: public:
vhdl_const_string(const string& value) vhdl_const_string(const char *value)
: vhdl_expr(vhdl_type::string(), true), value_(value) {} : vhdl_expr(vhdl_type::string(), true), value_(value) {}
void emit(std::ostream &of, int level) const; void emit(std::ostream &of, int level) const;
@ -199,7 +198,7 @@ private:
int64_t bits_to_int() const; int64_t bits_to_int() const;
char sign_bit() const; char sign_bit() const;
bool has_meta_bits() const; bool has_meta_bits() const;
std::string value_; std::string value_;
bool qualified_, signed_; bool qualified_, signed_;
}; };
@ -256,7 +255,7 @@ private:
class vhdl_expr_list : public vhdl_element { class vhdl_expr_list : public vhdl_element {
public: public:
~vhdl_expr_list(); ~vhdl_expr_list();
void emit(std::ostream &of, int level) const; void emit(std::ostream &of, int level) const;
bool empty() const { return exprs_.empty(); } bool empty() const { return exprs_.empty(); }
void add_expr(vhdl_expr *e); void add_expr(vhdl_expr *e);
@ -271,7 +270,7 @@ private:
*/ */
class vhdl_fcall : public vhdl_expr { class vhdl_fcall : public vhdl_expr {
public: public:
vhdl_fcall(const string& name, vhdl_type *rtype) vhdl_fcall(const char *name, vhdl_type *rtype)
: vhdl_expr(rtype), name_(name) {}; : vhdl_expr(rtype), name_(name) {};
~vhdl_fcall() {} ~vhdl_fcall() {}
@ -330,7 +329,7 @@ public:
vhdl_with_select_stmt(vhdl_expr *test, vhdl_var_ref *out) vhdl_with_select_stmt(vhdl_expr *test, vhdl_var_ref *out)
: test_(test), out_(out), others_(NULL) {} : test_(test), out_(out), others_(NULL) {}
~vhdl_with_select_stmt(); ~vhdl_with_select_stmt();
void emit(std::ostream &of, int level) const; void emit(std::ostream &of, int level) const;
void add_condition(vhdl_expr *value, vhdl_expr *cond, vhdl_expr *delay=NULL); void add_condition(vhdl_expr *value, vhdl_expr *cond, vhdl_expr *delay=NULL);
void add_default(vhdl_expr* value); void add_default(vhdl_expr* value);
@ -364,7 +363,7 @@ public:
class stmt_container { class stmt_container {
public: public:
~stmt_container(); ~stmt_container();
void add_stmt(vhdl_seq_stmt *stmt); void add_stmt(vhdl_seq_stmt *stmt);
void move_stmts_from(stmt_container *other); void move_stmts_from(stmt_container *other);
void emit(std::ostream &of, int level, bool newline=true) const; void emit(std::ostream &of, int level, bool newline=true) const;
@ -392,7 +391,7 @@ public:
protected: protected:
vhdl_var_ref *lhs_; vhdl_var_ref *lhs_;
vhdl_expr *rhs_, *after_; vhdl_expr *rhs_, *after_;
}; };
/* /*
@ -403,7 +402,7 @@ class vhdl_nbassign_stmt : public vhdl_abstract_assign_stmt {
public: public:
vhdl_nbassign_stmt(vhdl_var_ref *lhs, vhdl_expr *rhs) vhdl_nbassign_stmt(vhdl_var_ref *lhs, vhdl_expr *rhs)
: vhdl_abstract_assign_stmt(lhs, rhs) {} : vhdl_abstract_assign_stmt(lhs, rhs) {}
void emit(std::ostream &of, int level) const; void emit(std::ostream &of, int level) const;
}; };
@ -435,7 +434,7 @@ public:
vhdl_expr *expr = NULL) vhdl_expr *expr = NULL)
: type_(type), expr_(expr) {} : type_(type), expr_(expr) {}
~vhdl_wait_stmt(); ~vhdl_wait_stmt();
void emit(std::ostream &of, int level) const; void emit(std::ostream &of, int level) const;
void add_sensitivity(const std::string &s) { sensitivity_.push_back(s); } void add_sensitivity(const std::string &s) { sensitivity_.push_back(s); }
vhdl_wait_type_t get_type() const { return type_; } vhdl_wait_type_t get_type() const { return type_; }
@ -454,32 +453,15 @@ public:
}; };
enum vhdl_severity_t { class vhdl_assert_stmt : public vhdl_seq_stmt {
SEVERITY_NOTE,
SEVERITY_WARNING,
SEVERITY_ERROR,
SEVERITY_FAILURE
};
class vhdl_report_stmt : public vhdl_seq_stmt {
public: public:
vhdl_report_stmt(vhdl_expr *text, vhdl_assert_stmt(const char *reason)
vhdl_severity_t severity = SEVERITY_NOTE); : reason_(reason) {}
virtual ~vhdl_report_stmt() {}
virtual void emit(ostream& of, int level) const; void emit(std::ostream &of, int level) const;
void find_vars(vhdl_var_set_t& read, vhdl_var_set_t& write); void find_vars(vhdl_var_set_t& read, vhdl_var_set_t& write) {}
private: private:
vhdl_severity_t severity_; std::string reason_;
vhdl_expr *text_;
};
class vhdl_assert_stmt : public vhdl_report_stmt {
public:
vhdl_assert_stmt(const char *reason);
void emit(ostream &of, int level) const;
}; };
@ -498,7 +480,7 @@ private:
vhdl_expr *test; vhdl_expr *test;
stmt_container *container; stmt_container *container;
}; };
vhdl_expr *test_; vhdl_expr *test_;
stmt_container then_part_, else_part_; stmt_container then_part_, else_part_;
std::list<elsif> elsif_parts_; std::list<elsif> elsif_parts_;
@ -541,7 +523,7 @@ private:
class vhdl_loop_stmt : public vhdl_seq_stmt { class vhdl_loop_stmt : public vhdl_seq_stmt {
public: public:
virtual ~vhdl_loop_stmt() {} virtual ~vhdl_loop_stmt() {}
stmt_container *get_container() { return &stmts_; } stmt_container *get_container() { return &stmts_; }
void emit(std::ostream &of, int level) const; void emit(std::ostream &of, int level) const;
virtual void find_vars(vhdl_var_set_t& read, virtual void find_vars(vhdl_var_set_t& read,
@ -568,7 +550,7 @@ public:
vhdl_for_stmt(const char *lname, vhdl_expr *from, vhdl_expr *to) vhdl_for_stmt(const char *lname, vhdl_expr *from, vhdl_expr *to)
: lname_(lname), from_(from), to_(to) {} : lname_(lname), from_(from), to_(to) {}
~vhdl_for_stmt(); ~vhdl_for_stmt();
void emit(std::ostream &of, int level) const; void emit(std::ostream &of, int level) const;
void find_vars(vhdl_var_set_t& read, vhdl_var_set_t& write); void find_vars(vhdl_var_set_t& read, vhdl_var_set_t& write);
private: private:
@ -584,7 +566,7 @@ private:
class vhdl_pcall_stmt : public vhdl_seq_stmt { class vhdl_pcall_stmt : public vhdl_seq_stmt {
public: public:
vhdl_pcall_stmt(const char *name) : name_(name) {} vhdl_pcall_stmt(const char *name) : name_(name) {}
void emit(std::ostream &of, int level) const; void emit(std::ostream &of, int level) const;
void add_expr(vhdl_expr *e) { exprs_.add_expr(e); } void add_expr(vhdl_expr *e) { exprs_.add_expr(e); }
void find_vars(vhdl_var_set_t& read, vhdl_var_set_t& write); void find_vars(vhdl_var_set_t& read, vhdl_var_set_t& write);
@ -615,14 +597,14 @@ public:
// Return a new reference to this declaration // Return a new reference to this declaration
vhdl_var_ref* make_ref() const; vhdl_var_ref* make_ref() const;
// The different sorts of assignment statement // The different sorts of assignment statement
// ASSIGN_CONST is used to generate a variable to shadow a // ASSIGN_CONST is used to generate a variable to shadow a
// constant that cannot be assigned to (e.g. a function parameter) // constant that cannot be assigned to (e.g. a function parameter)
enum assign_type_t { ASSIGN_BLOCK, ASSIGN_NONBLOCK, ASSIGN_CONST }; enum assign_type_t { ASSIGN_BLOCK, ASSIGN_NONBLOCK, ASSIGN_CONST };
// Get the sort of assignment statement to generate for // Get the sort of assignment statement to generate for
// assignemnts to this declaration // assignments to this declaration
// For some sorts of declarations it doesn't make sense // For some sorts of declarations it doesn't make sense
// to assign to it so calling assignment_type just raises // to assign to it so calling assignment_type just raises
// an assertion failure // an assertion failure
@ -631,7 +613,7 @@ public:
// True if this declaration can be read from // True if this declaration can be read from
virtual bool is_readable() const { return true; } virtual bool is_readable() const { return true; }
// Modify this declaration so it can be read from // Modify this declaration so it can be read from
// This does nothing for most declaration types // This does nothing for most declaration types
virtual void ensure_readable() {} virtual void ensure_readable() {}
@ -643,7 +625,7 @@ protected:
}; };
typedef std::list<vhdl_decl*> decl_list_t; typedef std::list<vhdl_decl*> decl_list_t;
/* /*
* A forward declaration of a component. At the moment it is assumed * A forward declaration of a component. At the moment it is assumed
@ -773,7 +755,7 @@ class vhdl_scope {
public: public:
vhdl_scope(); vhdl_scope();
~vhdl_scope(); ~vhdl_scope();
void add_decl(vhdl_decl *decl); void add_decl(vhdl_decl *decl);
void add_forward_decl(vhdl_decl *decl); void add_forward_decl(vhdl_decl *decl);
vhdl_decl *get_decl(const std::string &name) const; vhdl_decl *get_decl(const std::string &name) const;
@ -781,15 +763,13 @@ public:
bool name_collides(const string& name) const; bool name_collides(const string& name) const;
bool contained_within(const vhdl_scope *other) const; bool contained_within(const vhdl_scope *other) const;
vhdl_scope *get_parent() const; vhdl_scope *get_parent() const;
bool empty() const { return decls_.empty(); } bool empty() const { return decls_.empty(); }
const decl_list_t &get_decls() const { return decls_; } const decl_list_t &get_decls() const { return decls_; }
void set_parent(vhdl_scope *p) { parent_ = p; } void set_parent(vhdl_scope *p) { parent_ = p; }
bool initializing() const { return init_; } bool initializing() const { return init_; }
void set_initializing(bool i); void set_initializing(bool i);
bool hoisted_initialiser() const;
void hoisted_initialiser(bool h);
void set_allow_signal_assignment(bool b) { sig_assign_ = b; } void set_allow_signal_assignment(bool b) { sig_assign_ = b; }
bool allow_signal_assignment() const { return sig_assign_; } bool allow_signal_assignment() const { return sig_assign_; }
@ -797,7 +777,6 @@ private:
decl_list_t decls_; decl_list_t decls_;
vhdl_scope *parent_; vhdl_scope *parent_;
bool init_, sig_assign_; bool init_, sig_assign_;
bool hoisted_init_;
}; };
@ -810,30 +789,21 @@ class vhdl_procedural {
public: public:
vhdl_procedural() : contains_wait_stmt_(false) {} vhdl_procedural() : contains_wait_stmt_(false) {}
virtual ~vhdl_procedural() {} virtual ~vhdl_procedural() {}
virtual stmt_container *get_container() { return &stmts_; } virtual stmt_container *get_container() { return &stmts_; }
virtual vhdl_scope *get_scope() { return &scope_; } virtual vhdl_scope *get_scope() { return &scope_; }
void added_wait_stmt() { contains_wait_stmt_ = true; } void added_wait_stmt() { contains_wait_stmt_ = true; }
bool contains_wait_stmt() const { return contains_wait_stmt_; } bool contains_wait_stmt() const { return contains_wait_stmt_; }
// Managing set of blocking assignment targets in this block
void add_blocking_target(vhdl_var_ref* ref);
bool is_blocking_target(vhdl_var_ref* ref) const;
protected: protected:
stmt_container stmts_; stmt_container stmts_;
vhdl_scope scope_; vhdl_scope scope_;
// If this is true then the body contains a `wait' statement // If this is true then the body contains a `wait' statement
// embedded in it somewhere // embedded in it somewhere
// If this is the case then we can't use a sensitvity list for // If this is the case then we can't use a sensitivity list for
// the process // the process
bool contains_wait_stmt_; bool contains_wait_stmt_;
// The set of variable we have performed a blocking
// assignment to
set<string> blocking_targets_;
}; };
@ -841,7 +811,7 @@ class vhdl_function : public vhdl_decl, public vhdl_procedural {
friend class vhdl_forward_fdecl; friend class vhdl_forward_fdecl;
public: public:
vhdl_function(const char *name, vhdl_type *ret_type); vhdl_function(const char *name, vhdl_type *ret_type);
virtual void emit(std::ostream &of, int level) const; virtual void emit(std::ostream &of, int level) const;
vhdl_scope *get_scope() { return &variables_; } vhdl_scope *get_scope() { return &variables_; }
void add_param(vhdl_param_decl *p) { scope_.add_decl(p); } void add_param(vhdl_param_decl *p) { scope_.add_decl(p); }
@ -911,7 +881,7 @@ public:
void set_time_units(int units, int precision); void set_time_units(int units, int precision);
friend vhdl_const_time* scale_time(const vhdl_entity* ent, uint64_t t); friend vhdl_const_time* scale_time(const vhdl_entity* ent, uint64_t t);
// Each entity has an associated depth which is how deep in // Each entity has an associated depth which is how deep in
// the Verilog module hierarchy it was found // the Verilog module hierarchy it was found
// This is used to limit the maximum depth of modules emitted // This is used to limit the maximum depth of modules emitted
@ -920,7 +890,7 @@ private:
std::string name_; std::string name_;
vhdl_arch *arch_; // Entity may only have a single architecture vhdl_arch *arch_; // Entity may only have a single architecture
vhdl_scope ports_; vhdl_scope ports_;
// Entities have an associated VHDL time unit // Entities have an associated VHDL time unit
// This is used to implement the Verilog timescale directive // This is used to implement the Verilog timescale directive
time_unit_t time_unit_; time_unit_t time_unit_;

View File

@ -1,4 +1,3 @@
// -*- mode: c++ -*-
#ifndef INC_VHDL_TARGET_H #ifndef INC_VHDL_TARGET_H
#define INC_VHDL_TARGET_H #define INC_VHDL_TARGET_H
@ -29,8 +28,10 @@ ivl_design_t get_vhdl_design();
vhdl_var_ref *nexus_to_var_ref(vhdl_scope *arch_scope, ivl_nexus_t nexus); vhdl_var_ref *nexus_to_var_ref(vhdl_scope *arch_scope, ivl_nexus_t nexus);
vhdl_var_ref* readable_ref(vhdl_scope* scope, ivl_nexus_t nex); vhdl_var_ref* readable_ref(vhdl_scope* scope, ivl_nexus_t nex);
string make_safe_name(ivl_signal_t sig); string make_safe_name(ivl_signal_t sig);
int draw_stask_display(vhdl_procedural *proc, stmt_container *container,
ivl_statement_t stmt, bool newline = true);
void prune_wait_for_0(stmt_container *container);
void require_support_function(support_function_t f); void require_support_function(support_function_t f);
#endif /* #ifndef INC_VHDL_TARGET_H */ #endif /* #ifndef INC_VHDL_TARGET_H */

View File

@ -86,7 +86,7 @@ std::string vhdl_type::get_string() const
case VHDL_TYPE_STD_ULOGIC: case VHDL_TYPE_STD_ULOGIC:
return std::string("std_ulogic"); return std::string("std_ulogic");
case VHDL_TYPE_STD_LOGIC_VECTOR: case VHDL_TYPE_STD_LOGIC_VECTOR:
return std::string("std_logic_vector"); return std::string("std_logic_vector");
case VHDL_TYPE_STRING: case VHDL_TYPE_STRING:
return std::string("String"); return std::string("String");
case VHDL_TYPE_LINE: case VHDL_TYPE_LINE:

View File

@ -57,7 +57,7 @@ public:
// Copy constructor // Copy constructor
vhdl_type(const vhdl_type &other); vhdl_type(const vhdl_type &other);
virtual ~vhdl_type(); virtual ~vhdl_type();
void emit(std::ostream &of, int level) const; void emit(std::ostream &of, int level) const;
@ -69,7 +69,7 @@ public:
int get_width() const { return msb_ - lsb_ + 1; } int get_width() const { return msb_ - lsb_ + 1; }
int get_msb() const { return msb_; } int get_msb() const { return msb_; }
int get_lsb() const { return lsb_; } int get_lsb() const { return lsb_; }
// Common types // Common types
static vhdl_type *std_logic(); static vhdl_type *std_logic();
static vhdl_type *std_ulogic(); static vhdl_type *std_ulogic();

View File

@ -105,12 +105,13 @@ static void draw_lpm_mux_ab(ivl_lpm_t net, const char*muxz)
static void draw_lpm_mux_nest(ivl_lpm_t net, const char*muxz) static void draw_lpm_mux_nest(ivl_lpm_t net, const char*muxz)
{ {
int idx, level; unsigned idx, level;
unsigned width = ivl_lpm_width(net); unsigned width = ivl_lpm_width(net);
unsigned swidth = ivl_lpm_selects(net); unsigned swidth = ivl_lpm_selects(net);
char*select_input; char*select_input;
assert(ivl_lpm_size(net) == (1 << swidth)); assert(swidth < sizeof(unsigned));
assert(ivl_lpm_size(net) == (1U << swidth));
select_input = strdup(draw_net_input(ivl_lpm_select(net))); select_input = strdup(draw_net_input(ivl_lpm_select(net)));

View File

@ -94,7 +94,8 @@ static char* draw_C4_to_string(ivl_net_const_t cptr)
for (idx = 0 ; idx < ivl_const_width(cptr) ; idx += 1) { for (idx = 0 ; idx < ivl_const_width(cptr) ; idx += 1) {
char bitchar = bits[ivl_const_width(cptr)-idx-1]; char bitchar = bits[ivl_const_width(cptr)-idx-1];
*dp++ = bitchar; *dp++ = bitchar;
assert((dp - result) < result_len); assert(dp >= result);
assert((unsigned)(dp - result) < result_len);
} }
strcpy(dp, ">"); strcpy(dp, ">");
@ -144,7 +145,8 @@ static char* draw_C8_to_string(ivl_net_const_t cptr,
assert(0); assert(0);
break; break;
} }
assert(dp - result < nresult); assert(dp >= result);
assert((unsigned)(dp - result) < nresult);
} }
strcpy(dp, ">"); strcpy(dp, ">");
@ -260,7 +262,8 @@ static char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr)
dp += ivl_logic_width(lptr); dp += ivl_logic_width(lptr);
*dp++ = '>'; *dp++ = '>';
*dp = 0; *dp = 0;
assert((dp-result) <= result_len); assert(dp >= result);
assert((unsigned)(dp - result) <= result_len);
return result; return result;
} else { } else {
char val[4]; char val[4];
@ -279,7 +282,8 @@ static char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr)
dp += 3*ivl_logic_width(lptr); dp += 3*ivl_logic_width(lptr);
*dp++ = '>'; *dp++ = '>';
*dp = 0; *dp = 0;
assert((dp-result) <= result_len); assert(dp >= result);
assert((unsigned)(dp - result) <= result_len);
return result; return result;
} }
} }
@ -297,7 +301,8 @@ static char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr)
dp += ivl_logic_width(lptr); dp += ivl_logic_width(lptr);
*dp++ = '>'; *dp++ = '>';
*dp = 0; *dp = 0;
assert((dp-result) <= result_len); assert(dp >= result);
assert((unsigned)(dp - result) <= result_len);
} else { } else {
char val[4]; char val[4];
@ -316,7 +321,8 @@ static char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr)
dp += 3*ivl_logic_width(lptr); dp += 3*ivl_logic_width(lptr);
*dp++ = '>'; *dp++ = '>';
*dp = 0; *dp = 0;
assert((dp-result) <= result_len); assert(dp >= result);
assert((unsigned)(dp - result) <= result_len);
} }
@ -705,7 +711,7 @@ static void draw_net_input_x(ivl_nexus_t nex,
if (res == IVL_SIT_UWIRE) { if (res == IVL_SIT_UWIRE) {
if (ndrivers > 1) { if (ndrivers > 1) {
unsigned uidx; unsigned uidx;
ivl_signal_t usig; ivl_signal_t usig = 0;
/* Find the uwire signal. */ /* Find the uwire signal. */
for (uidx = 0 ; uidx < ivl_nexus_ptrs(nex) ; uidx += 1) { for (uidx = 0 ; uidx < ivl_nexus_ptrs(nex) ; uidx += 1) {
ivl_nexus_ptr_t ptr = ivl_nexus_ptr(nex, uidx); ivl_nexus_ptr_t ptr = ivl_nexus_ptr(nex, uidx);

View File

@ -156,7 +156,7 @@ int draw_ufunc_real(ivl_expr_t expr)
ivl_scope_t def = ivl_expr_def(expr); ivl_scope_t def = ivl_expr_def(expr);
ivl_signal_t retval = ivl_scope_port(def, 0); ivl_signal_t retval = ivl_scope_port(def, 0);
int res = 0; int res = 0;
int idx; unsigned idx;
/* If this is an automatic function, allocate the local storage. */ /* If this is an automatic function, allocate the local storage. */
if (ivl_scope_is_auto(def)) { if (ivl_scope_is_auto(def)) {

View File

@ -282,7 +282,8 @@ static void draw_vpi_taskfunc_args(const char*call_string,
for (bit = wid ; bit > 0 ; bit -= 1) for (bit = wid ; bit > 0 ; bit -= 1)
*dp++ = bits[bit-1]; *dp++ = bits[bit-1];
*dp++ = 0; *dp++ = 0;
assert(dp - buffer <= sizeof buffer); assert(dp >= buffer);
assert((unsigned)(dp - buffer) <= sizeof buffer);
} }
args[idx].text = strdup(buffer); args[idx].text = strdup(buffer);
continue; continue;

View File

@ -929,9 +929,9 @@ static struct vector_info draw_binary_expr_le(ivl_expr_t expr,
case 'G': case 'G':
rv = draw_eval_expr_wid(re, owid, STUFF_OK_XZ); rv = draw_eval_expr_wid(re, owid, STUFF_OK_XZ);
if (number_is_immediate(le,16,0) && !number_is_unknown(le)) { if (number_is_immediate(le,16,0) && !number_is_unknown(le)) {
unsigned imm = get_number_immediate(le); long imm = get_number_immediate(le);
assert(imm >= 0); assert(imm >= 0);
fprintf(vvp_out, " %%cmpi/%c %u, %u, %u;\n", s_flag, fprintf(vvp_out, " %%cmpi/%c %u, %ld, %u;\n", s_flag,
rv.base, imm, rv.wid); rv.base, imm, rv.wid);
} else { } else {
lv = draw_eval_expr_wid(le, owid, STUFF_OK_XZ); lv = draw_eval_expr_wid(le, owid, STUFF_OK_XZ);
@ -945,9 +945,9 @@ static struct vector_info draw_binary_expr_le(ivl_expr_t expr,
case 'L': case 'L':
lv = draw_eval_expr_wid(le, owid, STUFF_OK_XZ); lv = draw_eval_expr_wid(le, owid, STUFF_OK_XZ);
if (number_is_immediate(re,16,0) && !number_is_unknown(re)) { if (number_is_immediate(re,16,0) && !number_is_unknown(re)) {
unsigned imm = get_number_immediate(re); long imm = get_number_immediate(re);
assert(imm >= 0); assert(imm >= 0);
fprintf(vvp_out, " %%cmpi/%c %u, %u, %u;\n", s_flag, fprintf(vvp_out, " %%cmpi/%c %u, %ld, %u;\n", s_flag,
lv.base, imm, lv.wid); lv.base, imm, lv.wid);
} else { } else {
rv = draw_eval_expr_wid(re, owid, STUFF_OK_XZ); rv = draw_eval_expr_wid(re, owid, STUFF_OK_XZ);
@ -961,9 +961,9 @@ static struct vector_info draw_binary_expr_le(ivl_expr_t expr,
case '<': case '<':
lv = draw_eval_expr_wid(le, owid, STUFF_OK_XZ); lv = draw_eval_expr_wid(le, owid, STUFF_OK_XZ);
if (number_is_immediate(re,16,0) && !number_is_unknown(re)) { if (number_is_immediate(re,16,0) && !number_is_unknown(re)) {
unsigned imm = get_number_immediate(re); long imm = get_number_immediate(re);
assert(imm >= 0); assert(imm >= 0);
fprintf(vvp_out, " %%cmpi/%c %u, %u, %u;\n", s_flag, fprintf(vvp_out, " %%cmpi/%c %u, %ld, %u;\n", s_flag,
lv.base, imm, lv.wid); lv.base, imm, lv.wid);
} else { } else {
rv = draw_eval_expr_wid(re, owid, STUFF_OK_XZ); rv = draw_eval_expr_wid(re, owid, STUFF_OK_XZ);
@ -976,9 +976,9 @@ static struct vector_info draw_binary_expr_le(ivl_expr_t expr,
case '>': case '>':
rv = draw_eval_expr_wid(re, owid, STUFF_OK_XZ); rv = draw_eval_expr_wid(re, owid, STUFF_OK_XZ);
if (number_is_immediate(le,16,0) && !number_is_unknown(le)) { if (number_is_immediate(le,16,0) && !number_is_unknown(le)) {
unsigned imm = get_number_immediate(le); long imm = get_number_immediate(le);
assert(imm >= 0); assert(imm >= 0);
fprintf(vvp_out, " %%cmpi/%c %u, %u, %u;\n", s_flag, fprintf(vvp_out, " %%cmpi/%c %u, %ld, %u;\n", s_flag,
rv.base, imm, rv.wid); rv.base, imm, rv.wid);
} else { } else {
lv = draw_eval_expr_wid(le, owid, STUFF_OK_XZ); lv = draw_eval_expr_wid(le, owid, STUFF_OK_XZ);
@ -1942,7 +1942,7 @@ static struct vector_info draw_number_expr(ivl_expr_t expr, unsigned wid)
/* /*
* This little helper function generates the instructions to pad a * This little helper function generates the instructions to pad a
* vector in place. It is assumed that the calling function has set up * vector in place. It is assumed that the calling function has set up
* the first sub_sidth bits of the dest vector, and the signed_flag is * the first sub_width bits of the dest vector, and the signed_flag is
* true if the extension is to be signed. * true if the extension is to be signed.
*/ */
static void pad_in_place(struct vector_info dest, unsigned sub_width, int signed_flag) static void pad_in_place(struct vector_info dest, unsigned sub_width, int signed_flag)
@ -2589,7 +2589,7 @@ static struct vector_info draw_select_unsized_literal(ivl_expr_t expr,
/* If we have an undefined index then just produce a 'bx result. */ /* If we have an undefined index then just produce a 'bx result. */
fprintf(vvp_out, " %%jmp/1 T_%d.%d, 4;\n", thread_count, lab_x); fprintf(vvp_out, " %%jmp/1 T_%d.%d, 4;\n", thread_count, lab_x);
/* If the subv result is a magic constant, then make a copy in /* If the subv result is a magic constant, then make a copy in
writable vector space and work from there instead. */ writable vector space and work from there instead. */
if (subv.base < 4) { if (subv.base < 4) {
res.base = allocate_vector(subv.wid); res.base = allocate_vector(subv.wid);
@ -2609,7 +2609,7 @@ static struct vector_info draw_select_unsized_literal(ivl_expr_t expr,
fprintf(vvp_out, " %%mov %u, %u, %u; Pad sub-expression to match width\n", fprintf(vvp_out, " %%mov %u, %u, %u; Pad sub-expression to match width\n",
res.base, subv.base, subv.wid); res.base, subv.base, subv.wid);
if (ivl_expr_signed(sube)) { if (ivl_expr_signed(sube)) {
int idx; unsigned idx;
for (idx = subv.wid ; idx < res.wid ; idx += 1) { for (idx = subv.wid ; idx < res.wid ; idx += 1) {
fprintf(vvp_out, " %%mov %u, %u, 1;\n", fprintf(vvp_out, " %%mov %u, %u, 1;\n",
res.base+idx, subv.base+subv.wid-1); res.base+idx, subv.base+subv.wid-1);

View File

@ -166,7 +166,7 @@ static int draw_number_real(ivl_expr_t expr)
/* If this is a negative number, then arrange for the 2's /* If this is a negative number, then arrange for the 2's
complement to be calculated as we scan through the complement to be calculated as we scan through the
value. Real values are sign-magnitude, and this negation value. Real values are sign-magnitude, and this negation
gets us a magnitide. */ gets us a magnitude. */
int negate = 0; int negate = 0;
int carry = 0; int carry = 0;

View File

@ -28,7 +28,7 @@
static ivl_signal_t find_path_source_port(ivl_delaypath_t path) static ivl_signal_t find_path_source_port(ivl_delaypath_t path)
{ {
int idx; unsigned idx;
ivl_nexus_t nex = ivl_path_source(path); ivl_nexus_t nex = ivl_path_source(path);
ivl_scope_t path_scope = ivl_path_scope(path); ivl_scope_t path_scope = ivl_path_scope(path);

View File

@ -260,9 +260,43 @@ const char*drive_string(ivl_drive_t drive)
* on. The last net is selected as the output of the nexus. * on. The last net is selected as the output of the nexus.
*/ */
/*
* When checking if we can elide a buffer we need to keep the buffer
* if both the input and output for the buffer are connected only
* to netlist signals. This routine performs this check on the
* given nexus.
*/
static unsigned is_netlist_signal(ivl_net_logic_t net, ivl_nexus_t nex)
{
unsigned idx, rtn;
/* Assume that this is a netlist signal. */
rtn = 1;
for (idx = 0; idx < ivl_nexus_ptrs(nex); idx += 1) {
ivl_nexus_ptr_t nptr;
ivl_signal_t sptr;
nptr = ivl_nexus_ptr(nex, idx);
/* Skip a pointer to the buffer we're checking. */
if (ivl_nexus_ptr_log(nptr) == net) continue;
/* Check to see if this is a netlist signal. */
sptr = ivl_nexus_ptr_sig(nptr);
if (sptr && !ivl_signal_local(sptr)) continue;
/* If we get here then this is not just a netlist signal. */
rtn = 0;
break;
}
return rtn;
}
/* /*
* This tests a bufz device against an output receiver, and determines * This tests a bufz device against an output receiver, and determines
* if the device can be skipped. If this function returns true, then a * if the device can be skipped. If this function returns false, then a
* gate will be generated for this node. Otherwise, the code generator * gate will be generated for this node. Otherwise, the code generator
* will connect its input to its output and skip the gate. * will connect its input to its output and skip the gate.
*/ */
@ -311,6 +345,14 @@ int can_elide_bufz(ivl_net_logic_t net, ivl_nexus_ptr_t nptr)
if (drive_count != 1) if (drive_count != 1)
return 0; return 0;
/* If both the input and output are netlist signal then we cannot
elide a BUFZ since it represents a continuous assignment. */
if (is_netlist_signal(net, ivl_logic_pin(net, 0)) &&
is_netlist_signal(net, ivl_logic_pin(net, 1)) &&
(ivl_logic_type(net) == IVL_LO_BUFZ)) {
return 0;
}
return 1; return 1;
} }
@ -887,14 +929,15 @@ static void draw_logic_in_scope(ivl_net_logic_t lptr)
/* Get all the input label that I will use for parameters to /* Get all the input label that I will use for parameters to
the functor that I create later. */ the functor that I create later. */
ninp = ivl_logic_pins(lptr) - 1; ninp = ivl_logic_pins(lptr) - 1;
assert(ninp >= 0);
input_strings = calloc(ninp, sizeof(char*)); input_strings = calloc(ninp, sizeof(char*));
for (pdx = 0 ; pdx < ninp ; pdx += 1) for (pdx = 0 ; pdx < (unsigned)ninp ; pdx += 1)
input_strings[pdx] = draw_net_input(ivl_logic_pin(lptr, pdx+1)); input_strings[pdx] = draw_net_input(ivl_logic_pin(lptr, pdx+1));
level = 0; level = 0;
while (ninp) { while (ninp) {
int inst; unsigned inst;
for (inst = 0; inst < ninp; inst += 4) { for (inst = 0; inst < (unsigned)ninp; inst += 4) {
if (ninp > 4) if (ninp > 4)
fprintf(vvp_out, "L_%p/%d/%d .functor %s %u", fprintf(vvp_out, "L_%p/%d/%d .functor %s %u",
lptr, level, inst, lcasc, vector_width); lptr, level, inst, lcasc, vector_width);
@ -907,7 +950,7 @@ static void draw_logic_in_scope(ivl_net_logic_t lptr)
fprintf(vvp_out, " [%u %u]", str0, str1); fprintf(vvp_out, " [%u %u]", str0, str1);
} }
for (pdx = inst; pdx < ninp && pdx < inst+4 ; pdx += 1) { for (pdx = inst; pdx < (unsigned)ninp && pdx < inst+4 ; pdx += 1) {
if (level) { if (level) {
fprintf(vvp_out, ", L_%p/%d/%d", fprintf(vvp_out, ", L_%p/%d/%d",
lptr, level - 1, pdx*4); lptr, level - 1, pdx*4);

View File

@ -42,6 +42,10 @@
#define FST_MACOSX #define FST_MACOSX
#endif #endif
#if defined(__CYGWIN__) && defined(__GNUC__)
#define FST_USE_FWRITE_COMBINING
#endif
/***********************/ /***********************/
/*** ***/ /*** ***/
@ -375,7 +379,7 @@ return(rc);
static int fstWriterVarint(FILE *handle, uint64_t v) static int fstWriterVarint(FILE *handle, uint64_t v)
{ {
uint64_t nxt; uint64_t nxt;
unsigned char buf[32]; unsigned char buf[10]; /* ceil(64/7) = 10 */
unsigned char *pnt = buf; unsigned char *pnt = buf;
int len; int len;
@ -391,6 +395,50 @@ fstFwrite(buf, len, 1, handle);
return(len); return(len);
} }
#ifndef FST_USE_FWRITE_COMBINING
static int fstWriterUint32WithVarint(FILE *handle, uint32_t *u, uint64_t v)
{
uint64_t nxt;
unsigned char buf[10 + sizeof(uint32_t)];
unsigned char *pnt = buf + sizeof(uint32_t);
int len;
memcpy(buf, u, sizeof(uint32_t));
while((nxt = v>>7))
{
*(pnt++) = (v&0x7f) | 0x80;
v = nxt;
}
*(pnt++) = (v&0x7f);
len = pnt-buf;
fstFwrite(buf, len, 1, handle);
return(len);
}
#else
static int fstWriterUint32WithVarint(FILE *handle, uint32_t *u, uint64_t v, const void *dbuf, size_t siz)
{
uint64_t nxt;
unsigned char buf[10 + sizeof(uint32_t) + siz]; /* gcc extension ok for cygwin */
unsigned char *pnt = buf + sizeof(uint32_t);
int len;
memcpy(buf, u, sizeof(uint32_t));
while((nxt = v>>7))
{
*(pnt++) = (v&0x7f) | 0x80;
v = nxt;
}
*(pnt++) = (v&0x7f);
memcpy(pnt, dbuf, siz);
len = pnt-buf + siz;
fstFwrite(buf, len, 1, handle);
return(len);
}
#endif
/***********************/ /***********************/
/*** ***/ /*** ***/
@ -1555,7 +1603,6 @@ size_t len;
if((xc) && (handle <= xc->maxhandle)) if((xc) && (handle <= xc->maxhandle))
{ {
uint32_t prev_chg;
uint32_t fpos; uint32_t fpos;
uint32_t *vm4ip; uint32_t *vm4ip;
@ -1573,14 +1620,15 @@ if((xc) && (handle <= xc->maxhandle))
if(!xc->is_initial_time) if(!xc->is_initial_time)
{ {
prev_chg = vm4ip[2];
fpos = xc->vchn_siz; fpos = xc->vchn_siz;
/* cygwin runs faster if these writes are combined, so the new fstWriterUint32WithVarint function, but should help with regular */
fstFwrite(&prev_chg, 1, sizeof(uint32_t), xc->vchn_handle); #ifndef FST_USE_FWRITE_COMBINING
xc->vchn_siz += 4; xc->vchn_siz += fstWriterUint32WithVarint(xc->vchn_handle, &vm4ip[2], xc->tchn_idx - vm4ip[3]); /* prev_chg is vm4ip[2] */
xc->vchn_siz += fstWriterVarint(xc->vchn_handle, xc->tchn_idx - vm4ip[3]); fstFwrite(buf, len, 1, xc->vchn_handle);
fstFwrite(buf, len, 1, xc->vchn_handle); xc->vchn_siz += len;
xc->vchn_siz += len; #else
xc->vchn_siz += fstWriterUint32WithVarint(xc->vchn_handle, &vm4ip[2], xc->tchn_idx - vm4ip[3], buf, len); /* do one fwrite op only */
#endif
vm4ip[3] = xc->tchn_idx; vm4ip[3] = xc->tchn_idx;
vm4ip[2] = fpos; vm4ip[2] = fpos;
} }

View File

@ -265,7 +265,8 @@ static unsigned int get_format_char(char **rtn, int ljust, int plus,
unsigned int ini_size = 512; /* The initial size of the buffer. */ unsigned int ini_size = 512; /* The initial size of the buffer. */
/* Make sure the width fits in the initial buffer. */ /* Make sure the width fits in the initial buffer. */
if (width+1 > ini_size) ini_size = width + 1; assert(width >= -1);
if ((unsigned int)(width+1) > ini_size) ini_size = width + 1;
/* The default return value is the full format. */ /* The default return value is the full format. */
result = malloc(ini_size*sizeof(char)); result = malloc(ini_size*sizeof(char));

View File

@ -545,7 +545,7 @@ static unsigned fread_word(FILE *fp, vpiHandle word,
* my local vector. */ * my local vector. */
val.format = vpiVectorVal; val.format = vpiVectorVal;
vpi_get_value(word, &val); vpi_get_value(word, &val);
for (bidx = 0; bidx < words; bidx += 1) { for (bidx = 0; (unsigned)bidx < words; bidx += 1) {
vector[bidx].aval = val.value.vector[bidx].aval; vector[bidx].aval = val.value.vector[bidx].aval;
vector[bidx].bval = val.value.vector[bidx].bval; vector[bidx].bval = val.value.vector[bidx].bval;
} }
@ -682,10 +682,11 @@ static PLI_INT32 sys_fread_calltf(PLI_BYTE8*name)
vector = calloc(words, sizeof(s_vpi_vecval)); vector = calloc(words, sizeof(s_vpi_vecval));
bpe = (width+7)/8; bpe = (width+7)/8;
assert(count >= 0);
if (is_mem) { if (is_mem) {
unsigned idx; unsigned idx;
rtn = 0; rtn = 0;
for (idx = 0; idx < count; idx += 1) { for (idx = 0; idx < (unsigned)count; idx += 1) {
vpiHandle word; vpiHandle word;
word = vpi_handle_by_index(mem_reg, start+(signed)idx); word = vpi_handle_by_index(mem_reg, start+(signed)idx);
rtn += fread_word(fp, word, words, bpe, vector); rtn += fread_word(fp, word, words, bpe, vector);

View File

@ -71,7 +71,8 @@ void sdf_select_instance(const char*celltype, const char*cellinst)
const char*src = cellinst; const char*src = cellinst;
const char*dp; const char*dp;
while ( (dp=strchr(src, '.')) ) { while ( (dp=strchr(src, '.')) ) {
int len = dp - src; unsigned len = dp - src;
assert(dp >= src);
assert(len < sizeof buffer); assert(len < sizeof buffer);
strncpy(buffer, src, len); strncpy(buffer, src, len);
buffer[len] = 0; buffer[len] = 0;

View File

@ -59,7 +59,7 @@ all: dep vvp@EXEEXT@ libvpi.a vvp.man
clean: clean:
rm -f *.o *~ parse.cc parse.h lexor.cc tables.cc rm -f *.o *~ parse.cc parse.h lexor.cc tables.cc
rm -rf dep vvp@EXEEXT@ libvpi.a parse.output vvp.man vvp.pdf vvp.exp rm -rf dep vvp@EXEEXT@ libvpi.a parse.output vvp.man vvp.ps vvp.pdf vvp.exp
distclean: clean distclean: clean
rm -f Makefile config.log rm -f Makefile config.log
@ -152,8 +152,11 @@ vvp.man: $(srcdir)/vvp.man.in ../version.exe
../version.exe `head -1 $(srcdir)/vvp.man.in`'\n' > $@ ../version.exe `head -1 $(srcdir)/vvp.man.in`'\n' > $@
tail -n +2 $(srcdir)/vvp.man.in >> $@ tail -n +2 $(srcdir)/vvp.man.in >> $@
vvp.pdf: vvp.man vvp.ps: vvp.man
$(MAN) -t $(srcdir)/vvp.man | $(PS2PDF) - vvp.pdf $(MAN) -t ./vvp.man > vvp.ps
vvp.pdf: vvp.ps
$(PS2PDF) vvp.ps vvp.pdf
ifeq (@MINGW32@,yes) ifeq (@MINGW32@,yes)
ifeq ($(MAN),none) ifeq ($(MAN),none)

View File

@ -769,7 +769,7 @@ static unsigned vpi_array_is_real(vvp_array_t arr)
assert(arr->array_count > 0); assert(arr->array_count > 0);
struct __vpiRealVar*rsig = vpip_realvar_from_handle(arr->nets[0]); struct __vpiRealVar*rsig = vpip_realvar_from_handle(arr->nets[0]);
if (rsig) { if (rsig) {
struct __vpiSignal*vsig = vpip_signal_from_handle(arr->nets[0]); struct __vpiSignal*vsig = vpip_signal_from_handle(arr->nets[0]);
assert(vsig == 0); assert(vsig == 0);
return 1U; return 1U;
} }
@ -1503,7 +1503,6 @@ void vpip_array_word_change(struct __vpiCallback*cb, vpiHandle obj)
void vpip_array_change(struct __vpiCallback*cb, vpiHandle obj) void vpip_array_change(struct __vpiCallback*cb, vpiHandle obj)
{ {
struct __vpiArray*arr = ARRAY_HANDLE(obj); struct __vpiArray*arr = ARRAY_HANDLE(obj);
cb->extra_data = -1; // This is a callback for every element. cb->extra_data = -1; // This is a callback for every element.
cb->next = arr->vpi_callbacks; cb->next = arr->vpi_callbacks;

View File

@ -69,7 +69,7 @@ void vvp_fun_concat::recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
vvp_context_t) vvp_context_t)
{ {
assert(bit.size() == wid); assert(bit.size() == wid);
unsigned pdx = port.port(); unsigned pdx = port.port();
if (vwid != wid_[pdx]) { if (vwid != wid_[pdx]) {

View File

@ -30,7 +30,7 @@
* *
* port-0: D input * port-0: D input
* port-1: Clock input * port-1: Clock input
* port-2: Clock Enagle input * port-2: Clock Enable input
* port-3: Asynchronous D input. * port-3: Asynchronous D input.
*/ */
class vvp_dff : public vvp_net_fun_t { class vvp_dff : public vvp_net_fun_t {

View File

@ -51,7 +51,7 @@ void waitable_hooks_s::run_waiting_threads_(vthread_t&threads)
vthread_t tmp = threads; vthread_t tmp = threads;
if (tmp == 0) return; if (tmp == 0) return;
threads = 0; threads = 0;
vthread_schedule_list(tmp); vthread_schedule_list(tmp);
} }

View File

@ -2,7 +2,7 @@
main .scope module, "main"; main .scope module, "main";
T0 %vpi_call 0 0 "$display", "Display the number: %b", 5'b0zx1; T0 %vpi_call 0 0 "$display", "Display the number: %b", 5'b0zx1;
%end; %end;
.thread T0; .thread T0;
:file_names 2; :file_names 2;

View File

@ -373,7 +373,7 @@ register to read the repetition count from (signed or unsigned).
%evctl/i sets the repetition to an immediate unsigned value. %evctl/i sets the repetition to an immediate unsigned value.
%evctl/c clears the event control information. This is needed if a %evctl/c clears the event control information. This is needed if a
%assign/e may be skiped since the %assign/e statements clear the %assign/e may be skipped since the %assign/e statements clear the
event control information and the other %evctl statements assert event control information and the other %evctl statements assert
that this information has been cleared. You can get an assert if that this information has been cleared. You can get an assert if
this information is not managed correctly. this information is not managed correctly.

View File

@ -65,9 +65,9 @@ extern void schedule_assign_array_word(vvp_array_t mem,
* Create an event to propagate the output of a net. * Create an event to propagate the output of a net.
*/ */
extern void schedule_propagate_plucked_vector(vvp_net_t*ptr, extern void schedule_propagate_plucked_vector(vvp_net_t*ptr,
vvp_time64_t delay, vvp_time64_t delay,
const vvp_vector4_t&val, const vvp_vector4_t&val,
unsigned adr, unsigned wid); unsigned adr, unsigned wid);
/* /*
* This is very similar to schedule_assign_vector, but generates an * This is very similar to schedule_assign_vector, but generates an

View File

@ -65,7 +65,7 @@ void vpip_mcd_init(FILE *log)
fd_table[idx].fp = NULL; fd_table[idx].fp = NULL;
fd_table[idx].filename = NULL; fd_table[idx].filename = NULL;
} }
mcd_table[0].fp = stdout; mcd_table[0].fp = stdout;
mcd_table[0].filename = strdup("stdout"); mcd_table[0].filename = strdup("stdout");

View File

@ -318,7 +318,7 @@ static void vthr_vec_get_value(vpiHandle ref, s_vpi_value*vp)
break; break;
case vpiObjTypeVal: case vpiObjTypeVal:
vp->format = vpiVectorVal; vp->format = vpiVectorVal;
case vpiVectorVal: case vpiVectorVal:
vp->value.vector = (s_vpi_vecval*) vp->value.vector = (s_vpi_vecval*)
need_result_buf((wid+31)/32*sizeof(s_vpi_vecval), RBUF_VAL); need_result_buf((wid+31)/32*sizeof(s_vpi_vecval), RBUF_VAL);

View File

@ -972,7 +972,7 @@ bool of_ASSIGN_V0(vthread_t thr, vvp_code_t cp)
vvp_net_ptr_t ptr (cp->net, 0); vvp_net_ptr_t ptr (cp->net, 0);
if (bit >= 4) { if (bit >= 4) {
// If the vector is not a synthetic one, then have the // If the vector is not a synthetic one, then have the
// scheduler pluck it direcly out of my vector space. // scheduler pluck it directly out of my vector space.
schedule_assign_plucked_vector(ptr, delay, thr->bits4, bit, wid); schedule_assign_plucked_vector(ptr, delay, thr->bits4, bit, wid);
} else { } else {
vvp_vector4_t value = vthread_bits_to_vector(thr, bit, wid); vvp_vector4_t value = vthread_bits_to_vector(thr, bit, wid);
@ -2078,7 +2078,7 @@ static unsigned long* divide_bits(unsigned long*ap, unsigned long*bp, unsigned w
ap[cur_ptr+btop+1]); ap[cur_ptr+btop+1]);
} }
// cur_res is a guestimate of the result this far. It // cur_res is a guesstimate of the result this far. It
// may be 1 too big. (But it will also be >0) Try it, // may be 1 too big. (But it will also be >0) Try it,
// and if the difference comes out negative, then adjust. // and if the difference comes out negative, then adjust.

View File

@ -291,7 +291,7 @@ vvp_island* compile_find_island(const char*island)
* *
* The <src> is a label in the domain outside the island, and the * The <src> is a label in the domain outside the island, and the
* <label> is in the domain inside the island. Since this port is * <label> is in the domain inside the island. Since this port is
* bi-directional, the <label> is also avaliable in the domain outside * bi-directional, the <label> is also available in the domain outside
* the island. The outside should use the <label> to access the nexus * the island. The outside should use the <label> to access the nexus
* that this port represents, because the island will resolve internal * that this port represents, because the island will resolve internal
* drivers with the external driver and make the output available on * drivers with the external driver and make the output available on

View File

@ -1212,7 +1212,7 @@ void vvp_vector4_t::mov(unsigned dst, unsigned src, unsigned cnt)
// Here we know that either the source or // Here we know that either the source or
// destination is unaligned, and also we know that // destination is unaligned, and also we know that
// the count is less then a full word. // the count is less than a full word.
unsigned long vmask = (1UL << trans) - 1; unsigned long vmask = (1UL << trans) - 1;
unsigned long tmp; unsigned long tmp;
@ -1870,8 +1870,8 @@ void vvp_vector4array_aa::reset_instance(vvp_context_t context)
for (unsigned idx = 0 ; idx < words_ ; idx += 1) { for (unsigned idx = 0 ; idx < words_ ; idx += 1) {
if (cell->abits_ptr_) { if (cell->abits_ptr_) {
for (unsigned n = 0 ; n < cnt ; n += 1) { for (unsigned n = 0 ; n < cnt ; n += 1) {
cell->abits_ptr_[n] = vvp_vector4_t::WORD_X_ABITS; cell->abits_ptr_[n] = vvp_vector4_t::WORD_X_ABITS;
cell->bbits_ptr_[n] = vvp_vector4_t::WORD_X_BBITS; cell->bbits_ptr_[n] = vvp_vector4_t::WORD_X_BBITS;
} }
} }
cell++; cell++;

View File

@ -65,7 +65,6 @@ typedef void*vvp_context_item_t;
inline vvp_context_t vvp_allocate_context(unsigned nitem) inline vvp_context_t vvp_allocate_context(unsigned nitem)
{ {
return (vvp_context_t)malloc((2 + nitem) * sizeof(void*)); return (vvp_context_t)malloc((2 + nitem) * sizeof(void*));
} }
@ -915,7 +914,7 @@ inline bool vvp_vector8_t::eeq(const vvp_vector8_t&that) const
return true; return true;
if (size_ <= sizeof val_) if (size_ <= sizeof val_)
// This is equivilent to memcmp(val_, that.val_, sizeof val_)==0 // This is equivalent to memcmp(val_, that.val_, sizeof val_)==0
return ptr_ == that.ptr_; return ptr_ == that.ptr_;
else else
return memcmp(ptr_, that.ptr_, size_) == 0; return memcmp(ptr_, that.ptr_, size_) == 0;
@ -1164,7 +1163,7 @@ class vvp_net_fil_t : public vvp_vpi_callback {
// bit value. If bits were changed by the force mask, then the // bit value. If bits were changed by the force mask, then the
// method returns REPL and the caller should propagate the rep // method returns REPL and the caller should propagate the rep
// value instead. If the function returns STOP, then all the // value instead. If the function returns STOP, then all the
// output bits are filtered by the force mask ans there is // output bits are filtered by the force mask and there is
// nothing to propagate. // nothing to propagate.
virtual prop_t filter_vec4(const vvp_vector4_t&bit, vvp_vector4_t&rep, virtual prop_t filter_vec4(const vvp_vector4_t&bit, vvp_vector4_t&rep,
unsigned base, unsigned vwid); unsigned base, unsigned vwid);
@ -1185,7 +1184,7 @@ class vvp_net_fil_t : public vvp_vpi_callback {
virtual unsigned filter_size() const =0; virtual unsigned filter_size() const =0;
public: public:
// Suport for force methods. These are calloed by the // Support for force methods. These are called by the
// vvp_net_t::force_* methods to set the force value and mask // vvp_net_t::force_* methods to set the force value and mask
// for the filter. // for the filter.
virtual void force_fil_vec4(const vvp_vector4_t&val, vvp_vector2_t mask) =0; virtual void force_fil_vec4(const vvp_vector4_t&val, vvp_vector2_t mask) =0;
@ -1228,7 +1227,7 @@ class vvp_net_fil_t : public vvp_vpi_callback {
// These templates are similar to filter_mask_, but are // These templates are similar to filter_mask_, but are
// idempotent. Then do not trigger callbacks or otherwise // idempotent. Then do not trigger callbacks or otherwise
// cause any locak changes. These methods are used to test // cause any local changes. These methods are used to test
// arbitrary values against the force mask. // arbitrary values against the force mask.
template <class T> prop_t filter_input_mask_(const T&val, const T&force, T&rep) const; template <class T> prop_t filter_input_mask_(const T&val, const T&force, T&rep) const;

View File

@ -91,7 +91,7 @@ class vvp_fun_signal_base : public vvp_net_fun_t {
/* /*
* Variables and wires can have their values accessed, so this base * Variables and wires can have their values accessed, so this base
* class offers the unified concept of an acessible value. * class offers the unified concept of an accessible value.
*/ */
class vvp_signal_value { class vvp_signal_value {
public: public:
@ -280,7 +280,7 @@ class vvp_wire_vec4 : public vvp_wire_base {
vvp_wire_vec4(unsigned wid, vvp_bit4_t init); vvp_wire_vec4(unsigned wid, vvp_bit4_t init);
// The main filter behavior for this class. These methods take // The main filter behavior for this class. These methods take
// the value that the node is driven to, and applies the firce // the value that the node is driven to, and applies the force
// filters. In wires, this also saves the driven value, so // filters. In wires, this also saves the driven value, so
// that when a force is released, we can revert to the driven value. // that when a force is released, we can revert to the driven value.
prop_t filter_vec4(const vvp_vector4_t&bit, vvp_vector4_t&rep, prop_t filter_vec4(const vvp_vector4_t&bit, vvp_vector4_t&rep,

View File

@ -394,7 +394,7 @@ static void __compile_real_net2(vvp_net_t*node, vvp_array_t array,
obj = vpip_make_real_var(name, node); obj = vpip_make_real_var(name, node);
compile_vpi_symbol(my_label, obj); compile_vpi_symbol(my_label, obj);
} }
// REMOVE ME! Giving the net a label is a legacy of the times // REMOVE ME! Giving the net a label is a legacy of the times
// when the .net was a functor of its own. In the long run, we // when the .net was a functor of its own. In the long run, we
// must fix the code generator to not rely on the label of the // must fix the code generator to not rely on the label of the