Revert bad merge from vhdl branch
This commit is contained in:
parent
7f2cb6afcd
commit
ec49f10e2d
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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_;
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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");
|
||||||
|
|
|
||||||
68
elab_expr.cc
68
elab_expr.cc
|
|
@ -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);
|
||||||
|
|
|
||||||
29
elab_lval.cc
29
elab_lval.cc
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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: "
|
||||||
|
|
|
||||||
28
eval_tree.cc
28
eval_tree.cc
|
|
@ -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;
|
||||||
|
|
|
||||||
126
examples/des.v
126
examples/des.v
|
|
@ -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];
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
2
main.cc
2
main.cc
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
||||||
16
net_expr.cc
16
net_expr.cc
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
163
netmisc.cc
163
netmisc.cc
|
|
@ -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
|
||||||
|
|
|
||||||
26
netmisc.h
26
netmisc.h
|
|
@ -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.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
16
nodangle.cc
16
nodangle.cc
|
|
@ -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. */
|
||||||
|
|
|
||||||
2
parse.y
2
parse.y
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
22
pform.cc
22
pform.cc
|
|
@ -62,10 +62,10 @@ void parm_to_defparam_list(const string¶m)
|
||||||
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¶m)
|
||||||
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¶m)
|
||||||
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¶m)
|
||||||
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¶m)
|
||||||
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();
|
||||||
|
|
|
||||||
2
pform.h
2
pform.h
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
387
tgt-vhdl/stmt.cc
387
tgt-vhdl/stmt.cc
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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));
|
||||||
|
|
|
||||||
|
|
@ -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_;
|
||||||
|
|
|
||||||
|
|
@ -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 */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
|
||||||
|
|
@ -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)));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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)) {
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
66
vpi/fstapi.c
66
vpi/fstapi.c
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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));
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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]) {
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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++;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue