Revert bad merge from vhdl branch

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

View File

@ -30,7 +30,7 @@ SHELL = /bin/sh
# The "suffix" is used as an installation suffix. It modifies certain
# key install paths/files such that a build and install of Icarus Verilog
# 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@
prefix = @prefix@
@ -240,7 +240,7 @@ iverilog-vpi.man: $(srcdir)/iverilog-vpi.man.in version.exe
tail -n +2 $(srcdir)/iverilog-vpi.man.in >> $@
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
$(PS2PDF) iverilog-vpi.ps iverilog-vpi.pdf

View File

@ -1,7 +1,7 @@
#ifndef __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
* 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_; }
ivl_dis_domain_t domain() const { return domain_; }
const ivl_nature_t potential() const { return potential_; }
const ivl_nature_t flow() const { return flow_; }
ivl_nature_t potential() const { return potential_; }
ivl_nature_t flow() const { return flow_; }
private:
perm_string name_;

View File

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

View File

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

View File

@ -64,7 +64,7 @@ Verilog source for use by other compilers.
.B -g1995\fI|\fP-g2001\fI|\fP-g2001-noconfig\fI|\fP-g2005\fI|\fP-g2009
Select the Verilog language \fIgeneration\fP to support in the
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
language. This flag is most useful to restrict the language to a set
supported by tools of specific generations, for compatibility with

View File

@ -169,8 +169,8 @@ typedef struct t_command_file {
p_command_file cmd_file_head = NULL; /* The FIFO head */
p_command_file cmd_file_tail = NULL; /* The FIFO tail */
/* Temprarily store parameter definition from command line and
* parse it after we have delt with command file
/* Temporarily store parameter definition from command line and
* parse it after we have dealt with command file
*/
static const char** defparm_base = 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
the lib\ivl$(suffix) to finish. */
{ char *s;
char basepath[4096], tmp[4096];
GetModuleFileName(NULL, tmp, sizeof tmp);
char basepath[4096], tmppath[4096];
GetModuleFileName(NULL, tmppath, sizeof tmppath);
/* 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);
ivl_root[MAXSIZE-1] = 0;
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
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. */
if (depfile) {
FILE*fd = fopen(depfile, "w");

View File

@ -729,7 +729,7 @@ NetExpr* PEBinary::elaborate_expr_base_rshift_(Design*des,
return tmp;
}
// Falback, handle the general case.
// Fallback, handle the general case.
if (expr_wid > 0)
lp = pad_to_width(lp, expr_wid, *this);
tmp = new NetEBShift(op_, lp, rp);
@ -1011,7 +1011,7 @@ unsigned PEBLeftWidth::test_width(Design*des, NetScope*scope,
&& wid_left > 0
&& wid_left < integer_width) {
wid_left = integer_width;
if (debug_elaborate)
cerr << get_fileline() << ": debug: "
<< "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)
wid = expr->expr_width();
if (debug_elaborate)
cerr << get_fileline() << ": debug: cast to " << wid
<< " bits" << endl;
@ -2494,11 +2494,7 @@ NetExpr* PEIdent::elaborate_expr_param_idx_up_(Design*des, NetScope*scope,
return result_ex;
}
if (par_msv >= par_lsv) {
if (par_lsv != 0) base = make_add_expr(base, -par_lsv);
} else {
base = make_sub_expr(par_lsv-wid+1, base);
}
base = normalize_variable_base(base, par_msv, par_lsv, wid, true);
NetExpr*tmp = par->dup_expr();
tmp = new NetESelect(tmp, base, wid);
@ -2578,13 +2574,7 @@ NetExpr* PEIdent::elaborate_expr_param_idx_do_(Design*des, NetScope*scope,
return result_ex;
}
if (par_msv >= par_lsv) {
if (long offset = par_lsv+wid-1) {
base = make_add_expr(base, -offset);
}
} else {
base = make_sub_expr(par_lsv, base);
}
base = normalize_variable_base(base, par_msv, par_lsv, wid, false);
NetExpr*tmp = par->dup_expr();
tmp = new NetESelect(tmp, base, wid);
@ -2610,7 +2600,7 @@ NetExpr* PEIdent::elaborate_expr_param_(Design*des,
if (!name_tail.index.empty())
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) {
perm_string name = peek_tail_name(path_);
cerr << get_fileline() << ": error: "
@ -2742,17 +2732,10 @@ NetExpr* PEIdent::elaborate_expr_param_(Design*des,
} else {
if (par_me) {
long par_mv = par_me->value().as_long();
long par_lv = par_le->value().as_long();
if (par_mv >= par_lv) {
mtmp = par_lv
? 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);
}
mtmp = normalize_variable_base(mtmp,
par_me->value().as_long(),
par_le->value().as_long(),
1, true);
}
/* 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.
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);
}
}
@ -2945,7 +2929,7 @@ NetExpr* PEIdent::elaborate_expr_net_part_(Design*des, NetScope*scope,
cerr << get_fileline() << ": : "
"Replacing select with a constant 'bx." << endl;
}
NetEConst*tmp = new NetEConst(verinum(verinum::Vx, 1, false));
tmp->set_line(*this);
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
// range.
ex = new NetEConst(verinum(net->sig()->sb_to_idx(lsv) +
ex = new NetEConst(verinum(net->sig()->sb_to_idx(lsv) +
offset));
if (warn_ob_select) {
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;
}
if (net->msi() > net->lsi()) {
if (long offset = net->lsi())
base = make_add_expr(base, -offset);
} else {
base = make_sub_expr(net->lsi()-wid+1, base);
}
base = normalize_variable_base(base, net->msi(), net->lsi(), wid, true);
NetESelect*ss = new NetESelect(net, base, wid);
ss->set_line(*this);
@ -3184,12 +3163,7 @@ NetExpr* PEIdent::elaborate_expr_net_idx_do_(Design*des, NetScope*scope,
return ss;
}
if (net->msi() > net->lsi()) {
if (long offset = net->lsi()+wid-1)
base = make_add_expr(base, -offset);
} else {
base = make_sub_expr(net->lsi(), base);
}
base = normalize_variable_base(base, net->msi(), net->lsi(), wid, false);
NetESelect*ss = new NetESelect(net, base, wid);
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
// expressions to convert calculated bit select
// values to canonical values that are used internally.
if (net->sig()->msb() < net->sig()->lsb()) {
ex = make_sub_expr(net->sig()->lsb(), ex);
} else {
ex = make_add_expr(ex, - net->sig()->lsb());
}
ex = normalize_variable_base(ex, net->sig()->msb(), net->sig()->lsb(),
1, true);
NetESelect*ss = new NetESelect(net, ex, 1);
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
// it. The disadvantage of doing this is that semantic errors
// 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)) {
verinum cval = tmp->value();
ivl_assert(*this, cval.len()==1);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2009 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2010 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* 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)
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() &&
use_sel != index_component_t::SEL_NONE) {
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.
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);
}
@ -342,7 +343,6 @@ bool PEIdent::elaborate_lval_net_bit_(Design*des,
index_tail.msb->test_width(des, scope, integer_width, integer_width,
expr_type_tmp, unsized_flag_tmp);
// Bit selects have a single select expression. Evaluate the
// constant value and treat it as a part select with a bit
// width of 1.
@ -357,10 +357,7 @@ bool PEIdent::elaborate_lval_net_bit_(Design*des,
if (mux) {
// Non-constant bit mux. Correct the mux for the range
// of the vector, then set the l-value part select expression.
if (reg->msb() < reg->lsb())
mux = make_sub_expr(reg->lsb(), mux);
else if (reg->lsb() != 0)
mux = make_add_expr(mux, - reg->lsb());
mux = normalize_variable_base(mux, reg->msb(), reg->lsb(), 1, true);
lv->set_part(mux, 1);
@ -535,20 +532,12 @@ bool PEIdent::elaborate_lval_net_idx_(Design*des,
} else {
/* Correct the mux for the range of the vector. */
if (use_sel == index_component_t::SEL_IDX_UP) {
if (reg->msb() > reg->lsb()) {
if (long offset = reg->lsb())
base = make_add_expr(base, -offset);
} else {
base = make_sub_expr(reg->lsb()-wid+1, base);
}
base = normalize_variable_base(base, reg->msb(), reg->lsb(),
wid, true);
} else {
// This is assumed to be a SEL_IDX_DO.
if (reg->msb() > reg->lsb()) {
if (long offset = reg->lsb()+wid-1)
base = make_add_expr(base, -offset);
} else {
base = make_sub_expr(reg->lsb(), base);
}
base = normalize_variable_base(base, reg->msb(), reg->lsb(),
wid, false);
}
}

View File

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

View File

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

View File

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

View File

@ -162,11 +162,11 @@ end
endmodule
module des(pt, key, ct, clk);
input [1:64] pt;
input [1:64] key;
output [1:64] ct;
input clk;
wire [1:48] k1x,k2x,k3x,k4x,k5x,k6x,k7x,k8x,k9x,k10x,k11x,k12x,k13x,k14x,k15x,k16x;
input [1:64] pt;
input [1:64] key;
output [1:64] ct;
input clk;
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] 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);
input [1:64] key;
output [1:28] c0x, d0x;
wire [1:56] XX;
input [1:64] key;
output [1:28] c0x, d0x;
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[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);
input [1:28] c,d;
output [1:48] k;
wire [1:56] YY;
input [1:28] c,d;
output [1:48] k;
wire [1:56] YY;
assign YY[1:28]=c; assign YY[29:56]=d;
@ -231,7 +231,7 @@ endmodule
module rol1(o, i);
output [1:28] o;
output [1:28] o;
input [1:28] i;
assign o={i[2:28],i[1]};
@ -240,7 +240,7 @@ endmodule
module rol2(o, i);
output [1:28] o;
output [1:28] o;
input [1:28] i;
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);
input [1:64] key;
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] d0x,d1x,d2x,d3x,d4x,d5x,d6x,d7x,d8x,d9x,d10x,d11x,d12x,d13x,d14x,d15x,d16x;
input [1:64] key;
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] d0x,d1x,d2x,d3x,d4x,d5x,d6x,d7x,d8x,d9x,d10x,d11x,d12x,d13x,d14x,d15x,d16x;
pc1 pc1(key, c0x, d0x);
@ -294,10 +294,10 @@ endmodule
module s1(clk, b, so);
input clk;
input [1:6] b;
output [1:4] so;
reg [1:4] so;
input clk;
input [1:6] b;
output [1:4] so;
reg [1:4] so;
always @(posedge clk)
casex(b)
@ -370,10 +370,10 @@ endmodule
module s2(clk, b, so);
input clk;
input [1:6] b;
output [1:4] so;
reg [1:4] so;
input clk;
input [1:6] b;
output [1:4] so;
reg [1:4] so;
always @(posedge clk)
casex(b)
@ -446,10 +446,10 @@ endmodule
module s3(clk, b, so);
input clk;
input [1:6] b;
output [1:4] so;
reg [1:4] so;
input clk;
input [1:6] b;
output [1:4] so;
reg [1:4] so;
always @(posedge clk)
casex(b)
@ -522,10 +522,10 @@ endmodule
module s4(clk, b, so);
input clk;
input [1:6] b;
output [1:4] so;
reg [1:4] so;
input clk;
input [1:6] b;
output [1:4] so;
reg [1:4] so;
always @(posedge clk)
casex(b)
@ -598,10 +598,10 @@ endmodule
module s5(clk, b, so);
input clk;
input [1:6] b;
output [1:4] so;
reg [1:4] so;
input clk;
input [1:6] b;
output [1:4] so;
reg [1:4] so;
always @(posedge clk)
casex(b)
@ -674,10 +674,10 @@ endmodule
module s6(clk, b, so);
input clk;
input [1:6] b;
output [1:4] so;
reg [1:4] so;
input clk;
input [1:6] b;
output [1:4] so;
reg [1:4] so;
always @(posedge clk)
casex(b)
@ -750,10 +750,10 @@ endmodule
module s7(clk, b, so);
input clk;
input [1:6] b;
output [1:4] so;
reg [1:4] so;
input clk;
input [1:6] b;
output [1:4] so;
reg [1:4] so;
always @(posedge clk)
casex(b)
@ -826,10 +826,10 @@ endmodule
module s8(clk, b, so);
input clk;
input [1:6] b;
output [1:4] so;
reg [1:4] so;
input clk;
input [1:6] b;
output [1:4] so;
reg [1:4] so;
always @(posedge clk)
casex(b)
@ -902,8 +902,8 @@ endmodule
module ip(pt, l0x, r0x);
input [1:64] pt;
output [1:32] l0x, r0x;
input [1:64] pt;
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[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);
input [1:48] e;
output [1:6] b1x,b2x,b3x,b4x,b5x,b6x,b7x,b8x;
input [1:48] k;
wire [1:48] XX;
input [1:48] e;
output [1:6] b1x,b2x,b3x,b4x,b5x,b6x,b7x,b8x;
input [1:48] k;
wire [1:48] XX;
assign XX = k ^ e;
assign b1x = XX[1:6];
@ -960,9 +960,9 @@ endmodule
module pp(so1x,so2x,so3x,so4x,so5x,so6x,so7x,so8x,ppo);
input [1:4] so1x,so2x,so3x,so4x,so5x,so6x,so7x,so8x;
output [1:32] ppo;
wire [1:32] XX;
input [1:4] so1x,so2x,so3x,so4x,so5x,so6x,so7x,so8x;
output [1:32] ppo;
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[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);
input [1:32] d,l;
output [1:32] q;
input [1:32] d,l;
output [1:32] q;
assign q = d ^ l;
@ -994,10 +994,10 @@ input [1:32] li, ri;
input [1:48] k;
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:4] so1x,so2x,so3x,so4x,so5x,so6x,so7x,so8x;
wire [1:32] ppo;
wire [1:32] ppo;
xp xp(ri, e);
desxor1 desxor1(e, b1x, b2x, b3x, b4x, b5x, b6x, b7x, b8x, k);
@ -1018,7 +1018,7 @@ endmodule
module fp(l,r,ct);
input [1:32] l,r;
input [1:32] l,r;
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];

View File

@ -55,12 +55,12 @@
module register (out, val, clk, oe);
output [7:0] out;
input [7:0] val;
input clk, oe;
input [7:0] val;
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);

View File

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

View File

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

View File

@ -607,7 +607,7 @@ extern double ivl_const_real(ivl_net_const_t net);
*
* The discipline domain will not be IVL_DIS_NONE. The "none" domain
* 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 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
* 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_lsb

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1829,7 +1829,7 @@ class NetPartSelect : public NetNode {
* that makes sense for the technology.
*
* 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.
*/
class NetBUFZ : public NetNode {
@ -3574,6 +3574,8 @@ class NetEParam : public NetExpr {
virtual ivl_variable_type_t expr_type() const;
virtual NetExpr* eval_tree(int prune_to_width = -1);
virtual NetEParam* dup_expr() const;
void solving(bool arg);
bool solving() const;
virtual void dump(ostream&) const;
@ -3582,6 +3584,7 @@ class NetEParam : public NetExpr {
NetScope*scope_;
typedef map<perm_string,NetScope::param_expr_t>::iterator ref_t;
ref_t reference_;
bool solving_;
NetEParam(class Design*des, NetScope*scope, ref_t ref);
};

View File

@ -161,7 +161,7 @@ NetNet* cast_to_real(Design*des, NetScope*scope, NetNet*src)
* NetEBAdd node that has the input expression and an expression made
* from the constant value.
*/
NetExpr* make_add_expr(NetExpr*expr, long val)
static NetExpr* make_add_expr(NetExpr*expr, long val)
{
if (val == 0)
return expr;
@ -190,10 +190,14 @@ NetExpr* make_add_expr(NetExpr*expr, long val)
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());
val_v.has_sign(true);
NetEConst*val_c = new NetEConst(val_v);
val_c->set_line(*expr);
@ -203,6 +207,150 @@ NetExpr* make_sub_expr(long val, NetExpr*expr)
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)
{
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)
{
assert(expr);
if (dynamic_cast<NetEConst*>(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);
if (tmp != 0) {
@ -423,7 +578,7 @@ const char *human_readable_op(const char op, bool unary)
case '>': type = ">"; break;
case 'L': type = "<="; break;
case 'G': type = ">="; break;
case '^': type = "^"; break; // XOR
case 'X': type = "~^"; break; // XNOR
case '&': type = "&"; break; // Bitwise AND

View File

@ -91,6 +91,15 @@ extern NetExpr*condition_reduce(NetExpr*expr);
*/
extern NetNet*crop_to_width(Design*des, NetNet*n, unsigned w);
/*
* 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
* 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*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.
*/

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2009 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2010 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* 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)
return;
/* Cannot delete the ports of tasks or functions. There are
too many places where they are referenced. */
if ((sig->port_type() != NetNet::NOT_A_PORT)
&& (sig->scope()->type() == NetScope::TASK))
return;
if ((sig->port_type() != NetNet::NOT_A_PORT)
&& (sig->scope()->type() == NetScope::FUNC))
/* Cannot delete the ports of tasks, functions or modules. There
are too many places where they are referenced. */
if ((sig->port_type() != NetNet::NOT_A_PORT) &&
((sig->scope()->type() == NetScope::TASK) ||
(sig->scope()->type() == NetScope::FUNC) ||
(sig->scope()->type() == NetScope::MODULE)))
return;
/* Can't delete ports of cells. */

View File

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

View File

@ -78,7 +78,7 @@ extern bool have_timeunit_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.
*/
extern verinum*make_unsized_dec(const char*txt);

View File

@ -62,10 +62,10 @@ void parm_to_defparam_list(const string&param)
key = strdup(param.substr(0, off).c_str());
value = strdup(param.substr(off+1).c_str());
}
// Resolve hierarchical name for defparam. Remember
// 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;
char *nkey = key;
char *ptr = strchr(key, '.');
@ -109,7 +109,7 @@ void parm_to_defparam_list(const string&param)
ptr = strchr(nkey, '.');
}
name.push_back(name_component_t(lex_strings.make(nkey)));
// Resolve value to PExpr class. Should support all kind of constant
// format including based number, dec number, real number and string.
if (*value == '"') { // string type
@ -127,13 +127,13 @@ void parm_to_defparam_list(const string&param)
cerr << "<command line>: error: missing close quote of string for defparam: " << name << endl;
else if (*(buf_ptr+1) != 0) { // '"' appears within string with no escape
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;
}
*buf_ptr = '\0';
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.
char *nchar = strcpy(new char [strlen(buf_ptr)+1], buf_ptr);
PExpr* ndec = new PEString(nchar);
@ -144,7 +144,7 @@ void parm_to_defparam_list(const string&param)
char *num = strchr(value, '\'');
if (num != 0) {
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
// in hex format
if (strchr(num, 'h') || strchr(num, 'H'))
@ -165,17 +165,17 @@ void parm_to_defparam_list(const string&param)
free(value);
return;
}
// BASED_NUMBER with size, something like - scope.parameter=2'b11
if (num != value) {
*num = 0;
verinum *siz = make_unsized_dec(value);
val = pform_verinum_with_size(siz, val, "<command line>", 0);
}
PExpr* ndec = new PENumber(val);
Module::user_defparms.push_back( make_pair(name, ndec) );
}
else {
// 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;
}
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)
{
LineInfo*lni = new LineInfo();

View File

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

View File

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

View File

@ -50,7 +50,7 @@ dep:
mv $*.d dep
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)
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
clean:
rm -rf $(O) dep vhdl.tgt
rm -rf $(O) dep vhdl.tgt
distclean: clean
rm -f Makefile config.log

View File

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

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

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

View File

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

View File

@ -36,11 +36,11 @@ static vhdl_expr *inputs_to_expr(vhdl_scope *scope, vhdl_binop_t op,
// the program has already been type checked
vhdl_binop_expr *gate =
new vhdl_binop_expr(op, vhdl_type::std_logic());
int npins = ivl_logic_pins(log);
for (int i = 1; i < npins; i++) {
ivl_nexus_t input = ivl_logic_pin(log, i);
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);
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)
@ -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);
vhdl_var_ref *lhs = nexus_to_var_ref(arch->get_scope(), output);
assert(lhs);
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));
@ -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;
cmp = new vhdl_binop_expr(sel, op, zero, NULL);
}
ivl_signal_t sig = find_signal_named(lhs->get_name(), arch->get_scope());
char zbit;
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)
{
ivl_udp_t udp = ivl_logic_udp(log);
// As with regular case statements, the expression in a
// `with .. select' statement must be "locally static".
// This is achieved by first combining the inputs into
// a temporary
ostringstream ss;
ss << ivl_logic_basename(log) << "_Tmp";
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
// or some strict VHDL compilers will complain
ws->add_default(new vhdl_const_bit('X'));
int nrows = ivl_udp_rows(udp);
for (int i = 0; i < nrows; i++) {
const char *row = ivl_udp_row(udp, i);
vhdl_expr *value = new vhdl_const_bit(row[nin]);
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;
vhdl_type *tmp_type = vhdl_type::std_logic_vector(msb, 0);
proc->get_scope()->add_decl(new vhdl_var_decl("UDP_Inputs", tmp_type));
// Concatenate the inputs into a single expression that can be
// used as the test in a case statement (this can't be inserted
// 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);
vhdl_expr *tmp_rhs = NULL;
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
(new vhdl_assign_stmt(new vhdl_var_ref("UDP_Inputs", NULL), tmp_rhs));
arch->add_stmt(proc);
}
@ -273,18 +273,18 @@ void draw_logic(vhdl_arch *arch, ivl_net_logic_t log)
udp_logic(arch, log);
break;
default:
{
{
// The output is always pin zero
ivl_nexus_t output = ivl_logic_pin(log, 0);
vhdl_var_ref *lhs = nexus_to_var_ref(arch->get_scope(), output);
vhdl_expr *rhs = translate_logic_inputs(arch->get_scope(), log);
vhdl_cassign_stmt *ass = new vhdl_cassign_stmt(lhs, rhs);
ivl_expr_t delay = ivl_logic_delay(log, 1);
if (delay)
ass->set_after(translate_time_expr(delay));
arch->add_stmt(ass);
}
}

View File

@ -47,7 +47,7 @@ static vhdl_expr *concat_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm)
vhdl_type::type_for(ivl_lpm_width(lpm), ivl_lpm_signed(lpm) != 0);
vhdl_binop_expr *expr =
new vhdl_binop_expr(VHDL_BINOP_CONCAT, result_type);
for (int i = ivl_lpm_size(lpm) - 1; i >= 0; i--) {
vhdl_expr *e = readable_ref(scope, ivl_lpm_data(lpm, i));
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::type_for(out_width, ivl_lpm_signed(lpm) != 0);
vhdl_binop_expr *expr = new vhdl_binop_expr(op, result_type);
for (int i = 0; i < 2; i++) {
vhdl_expr *e = readable_ref(scope, ivl_lpm_data(lpm, i));
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));
}
if (op == VHDL_BINOP_MULT) {
// Need to resize the output to the desired size,
// as this does not happen automatically in VHDL
vhdl_fcall *resize =
new vhdl_fcall("Resize", vhdl_type::nsigned(out_width));
resize->add_expr(expr);
resize->add_expr(new vhdl_const_int(out_width));
return resize;
}
else
@ -106,7 +106,7 @@ static vhdl_expr *rel_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm, vhdl_binop_t
delete lhs;
return NULL;
}
// Ensure LHS and RHS are the same type
if (lhs->get_type() != rhs->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));
if (NULL == selfrom)
return NULL;
vhdl_expr *off = part_select_base(scope, lpm);;
if (NULL == off)
return NULL;
if (selfrom->get_type()->get_width() > 1)
selfrom->set_slice(off, ivl_lpm_width(lpm) - 1);
return selfrom;
}
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));
}
@ -171,13 +171,13 @@ static vhdl_expr *reduction_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm,
require_support_function(f);
vhdl_fcall *fcall = new vhdl_fcall(support_function::function_name(f),
vhdl_type::std_logic());
vhdl_type std_logic_vector(VHDL_TYPE_STD_LOGIC_VECTOR);
vhdl_type std_logic_vector(VHDL_TYPE_STD_LOGIC_VECTOR);
fcall->add_expr(ref->cast(&std_logic_vector));
result = fcall;
}
}
if (invert)
return new vhdl_unaryop_expr
(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);
if (!seen_signal_before(array))
return NULL;
const char *renamed = get_renamed_signal(array).c_str();
vhdl_decl *adecl = scope->get_decl(renamed);
assert(adecl);
vhdl_type *atype = new vhdl_type(*adecl->get_type());
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;
return NULL;
}
vhdl_var_ref *ref = new vhdl_var_ref(renamed, atype);
vhdl_type integer(VHDL_TYPE_INTEGER);
ref->set_slice(select->cast(&integer));
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 *rhs = readable_ref(scope, ivl_lpm_data(lpm, 1));
if (!lhs || !rhs)
return NULL;
return NULL;
// The RHS must be an integer
vhdl_type integer(VHDL_TYPE_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_expr *s0 = readable_ref(scope, ivl_lpm_data(lpm, 0));
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 *t1 =
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));
// 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)
return draw_mux_lpm(arch, lpm);
vhdl_expr *f = lpm_to_expr(arch->get_scope(), lpm);
if (NULL == f)
return 1;
vhdl_var_ref *out = nexus_to_var_ref(arch->get_scope(), ivl_lpm_q(lpm));
if (ivl_lpm_type(lpm) == IVL_LPM_PART_PV) {
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 =
out->get_type()->get_name() == VHDL_TYPE_STD_LOGIC
&& f->get_type()->get_name() == VHDL_TYPE_BOOLEAN;
if (bool_to_logic) {
vhdl_cassign_stmt* s =
new vhdl_cassign_stmt(out, new vhdl_const_bit('0'));
s->add_condition(new vhdl_const_bit('1'), f);
arch->add_stmt(s);
}
else
else
arch->add_stmt(new vhdl_cassign_stmt(out, f->cast(out->get_type())));
return 0;
}

View File

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

View File

@ -42,7 +42,7 @@ struct scope_nexus_t {
string tmpname; // A new temporary signal
list<ivl_signal_t> connect; // Other signals to wire together
};
/*
* This structure is stored in the private part of each nexus.
* 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,
ivl_signal_t sig, unsigned pin)
{
{
scope_nexus_t *sn;
if ((sn = visible_nexus(priv, scope))) {
assert(sn->tmpname == "");
// Remember to connect this signal up later
// 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)
@ -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;
width = 0;
for (unsigned idx = 0; idx < ivl_nexus_ptrs(nex); idx += 1) {
ivl_signal_type_t stype;
ivl_nexus_ptr_t ptr = ivl_nexus_ptr(nex, idx);
ivl_signal_t sig = ivl_nexus_ptr_sig(ptr);
if (sig == 0)
continue;
width = ivl_signal_width(sig);
stype = ivl_signal_type(sig);
if (stype == IVL_SIT_TRI)
continue;
@ -143,7 +143,7 @@ static ivl_signal_type_t signal_type_of_nexus(ivl_nexus_t nex, int &width)
continue;
out = stype;
}
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.
*/
void draw_nexus(ivl_nexus_t nexus)
{
{
nexus_private_t *priv = new nexus_private_t;
int nexus_signal_width = -1;
priv->const_driver = NULL;
int nptrs = ivl_nexus_ptrs(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
for (int i = 0; i < nptrs; i++) {
ivl_nexus_ptr_t nexus_ptr = ivl_nexus_ptr(nexus, i);
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);
if (scope) {
unsigned pin = ivl_nexus_ptr_pin(nexus_ptr);
@ -181,7 +181,7 @@ void draw_nexus(ivl_nexus_t nexus)
// inputs and outputs
for (int i = 0; i < nptrs; i++) {
ivl_nexus_ptr_t nexus_ptr = ivl_nexus_ptr(nexus, i);
ivl_net_logic_t log;
ivl_lpm_t lpm;
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);
if (!is_default_scope_instance(log_scope))
continue;
vhdl_entity *ent = find_entity(log_scope);
assert(ent);
vhdl_scope *vhdl_scope = ent->get_arch()->get_scope();
if (visible_nexus(priv, 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
vhdl_type *type =
vhdl_type::type_for(ivl_logic_width(log), false);
ostringstream ss;
ss << "LO" << ivl_logic_basename(log);
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);
vhdl_entity *ent = find_entity(lpm_scope);
assert(ent);
vhdl_scope *vhdl_scope = ent->get_arch()->get_scope();
if (visible_nexus(priv, 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;
else
lpm_temp_width = ivl_lpm_width(lpm);
vhdl_type *type = vhdl_type::type_for(lpm_temp_width,
ivl_lpm_signed(lpm) != 0);
ostringstream ss;
@ -243,7 +243,7 @@ void draw_nexus(ivl_nexus_t nexus)
if (!vhdl_scope->have_declared(ss.str()))
vhdl_scope->add_decl(new vhdl_signal_decl(ss.str().c_str(), type));
link_scope_to_nexus_tmp(priv, vhdl_scope, ss.str());
}
@ -274,7 +274,7 @@ void draw_nexus(ivl_nexus_t nexus)
if (ndrivers == 0) {
char def = 0;
int width;
switch (signal_type_of_nexus(nexus, width)) {
case IVL_SIT_TRI:
case IVL_SIT_UWIRE:
@ -305,7 +305,7 @@ void draw_nexus(ivl_nexus_t nexus)
priv->const_driver = new vhdl_const_bit(def);
}
}
// Save the private data in the nexus
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)
{
if (ivl_nexus_get_private(nexus) == NULL)
if (ivl_nexus_get_private(nexus) == NULL)
draw_nexus(nexus);
}
/*
* Translate a nexus to a variable reference. Given a nexus and a
* 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)
{
seen_nexus(nexus);
nexus_private_t *priv =
static_cast<nexus_private_t*>(ivl_nexus_get_private(nexus));
unsigned pin;
string renamed(visible_nexus_signal_name(priv, scope, &pin));
vhdl_decl *decl = scope->get_decl(renamed);
assert(decl);
vhdl_type *type = new vhdl_type(*(decl->get_type()));
vhdl_var_ref *ref = new vhdl_var_ref(renamed.c_str(), type);
if (decl->get_type()->get_name() == VHDL_TYPE_ARRAY)
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* ref = nexus_to_var_ref(scope, nex);
vhdl_decl* decl = scope->get_decl(ref->get_name());
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)
{
debug_msg("Declaring logic in scope type %s", ivl_scope_tname(scope));
int nlogs = ivl_scope_logs(scope);
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
@ -422,7 +422,7 @@ static string valid_entity_name(const string& module_name)
name = "module" + name;
if (*name.rbegin() == '_')
name += "module";
if (is_vhdl_reserved_word(name))
name += "_module";
@ -434,7 +434,7 @@ static string valid_entity_name(const string& module_name)
ss.str("");
ss << name << i++;
}
return ss.str();
}
@ -445,7 +445,7 @@ string make_safe_name(ivl_signal_t sig)
if (ivl_signal_local(sig))
base = "tmp" + base;
if (base[0] == '_')
base = "sig" + base;
@ -454,14 +454,14 @@ string make_safe_name(ivl_signal_t sig)
// Can't have two consecutive underscores
replace_consecutive_underscores(base);
// A signal name may not be the same as a component name
if (find_entity(base) != NULL)
base += "_sig";
if (is_vhdl_reserved_word(base))
base += "_sig";
return base;
}
@ -478,7 +478,7 @@ static void avoid_name_collision(string& name, vhdl_scope* scope)
ss.str("");
ss << name << i++;
} while (scope->name_collides(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++) {
ivl_parameter_t param = ivl_scope_param(scope, i);
ivl_expr_t e = ivl_parameter_expr(param);
if (ivl_expr_type(e) == IVL_EX_NUMBER) {
vhdl_expr* value = translate_expr(e);
assert(value);
value = value->cast(vhdl_type::integer());
suffix << "_" << ivl_parameter_basename(param);
value->emit(suffix, 0);
delete value;
}
else {
error("Only numeric genvars supported at the moment");
return "_ERROR"; // Never used
}
}
}
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));
name += genvar_unique_suffix(scope);
avoid_name_collision(name, ent->get_arch()->get_scope());
rename_signal(sig, name);
vhdl_type *sig_type;
unsigned dimensions = ivl_signal_dimensions(sig);
if (dimensions > 0) {
// Arrays are implemented by generating a separate type
// declaration for each array, and then declaring a
// signal of that type
if (dimensions > 1) {
error("> 1 dimension arrays not implemented yet");
return;
}
string type_name = name + "_Type";
vhdl_type *base_type =
vhdl_type::type_for(ivl_signal_width(sig), ivl_signal_signed(sig) != 0);
int lsb = ivl_signal_array_base(sig);
int msb = lsb + ivl_signal_array_count(sig) - 1;
vhdl_type *array_type =
vhdl_type::array_of(base_type, type_name, msb, lsb);
vhdl_decl *array_decl = new vhdl_type_decl(type_name.c_str(), array_type);
ent->get_arch()->get_scope()->add_decl(array_decl);
sig_type = new vhdl_type(*array_type);
}
else {
@ -562,15 +562,15 @@ static void declare_one_signal(vhdl_entity *ent, ivl_signal_t sig,
ivl_signal_signed(sig) != 0,
0, ivl_signal_type(sig) == IVL_SIT_UWIRE);
}
ivl_signal_port_t mode = ivl_signal_port(sig);
switch (mode) {
case IVL_SIP_NONE:
{
vhdl_decl *decl = new vhdl_signal_decl(name.c_str(), sig_type);
ostringstream ss;
if (ivl_signal_local(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);
}
decl->set_comment(ss.str().c_str());
ent->get_arch()->get_scope()->add_decl(decl);
}
break;
@ -591,10 +591,10 @@ static void declare_one_signal(vhdl_entity *ent, ivl_signal_t sig,
case IVL_SIP_OUTPUT:
{
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);
}
if (ivl_signal_type(sig) == IVL_SIT_REG) {
// A registered output
// 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);
newname += "_Reg";
rename_signal(sig, newname.c_str());
vhdl_type *reg_type = new vhdl_type(*sig_type);
ent->get_arch()->get_scope()->add_decl
(new vhdl_signal_decl(newname.c_str(), reg_type));
// Create a concurrent assignment statement to
// connect the register to the output
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)
{
debug_msg("Declaring signals in scope type %s", ivl_scope_tname(scope));
int nsigs = ivl_scope_sigs(scope);
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)
declare_one_signal(ent, sig, scope);
}
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)
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,
vhdl_comp_inst *inst)
{
{
// TODO: Work for multiple words
ivl_nexus_t nexus = ivl_signal_nex(to, 0);
seen_nexus(nexus);
@ -699,14 +699,14 @@ static void map_signal(ivl_signal_t to, vhdl_entity *parent,
&& !arch_scope->have_declared(name + "_Readable")) {
vhdl_decl* tmp_decl =
new vhdl_signal_decl(name + "_Readable", ref->get_type());
// Add a comment to explain what this is for
tmp_decl->set_comment("Needed to connect outputs");
arch_scope->add_decl(tmp_decl);
parent->get_arch()->add_stmt
(new vhdl_cassign_stmt(from_decl->make_ref(), tmp_decl->make_ref()));
map_to = tmp_decl->make_ref();
}
else
@ -719,7 +719,7 @@ static void map_signal(ivl_signal_t to, vhdl_entity *parent,
else {
// This nexus isn't attached to anything in the parent
return;
}
}
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);
for (int i = 0; i < nsigs; i++) {
ivl_signal_t sig = ivl_scope_sig(scope, i);
ivl_signal_port_t mode = ivl_signal_port(sig);
switch (mode) {
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_INOUT:
map_signal(sig, parent, inst);
break;
break;
default:
assert(false);
}
}
}
}
@ -788,9 +788,9 @@ static int draw_function(ivl_scope_t scope, ivl_scope_t parent)
vhdl_type *sigtype =
vhdl_type::type_for(ivl_signal_width(sig),
ivl_signal_signed(sig) != 0);
string signame(make_safe_name(sig));
switch (ivl_signal_port(sig)) {
case IVL_SIP_INPUT:
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
assert(false);
}
remember_signal(sig, func->get_scope());
rename_signal(sig, signame);
}
int nsigs = ivl_scope_sigs(scope);
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) {
vhdl_type *sigtype =
vhdl_type::type_for(
ivl_signal_width(sig),
ivl_signal_signed(sig) != 0);
string signame(make_safe_name(sig));
func->get_scope()->add_decl(
new vhdl_var_decl(signame, sigtype));
remember_signal(sig, func->get_scope());
rename_signal(sig, signame);
}
}
// Non-blocking assignment not allowed in functions
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 "
<< ivl_scope_def_file(scope) << ":" << ivl_scope_def_lineno(scope);
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;
}
@ -867,14 +867,14 @@ static int draw_task(ivl_scope_t scope, ivl_scope_t parent)
assert(ent);
const char *taskname = ivl_scope_tname(scope);
int nsigs = ivl_scope_sigs(scope);
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::type_for(ivl_signal_width(sig),
ivl_signal_signed(sig) != 0);
string signame(make_safe_name(sig));
// 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) << ":"
<< ivl_signal_lineno(sig) << " (in task " << taskname << ")";
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());
rename_signal(sig, signame);
}
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
const string tname = valid_entity_name(ivl_scope_tname(scope));
// Verilog does not have the entity/architecture distinction
// so we always create a pair and associate the architecture
// 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_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());
ent->set_comment(ss.str());
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))
return 0; // Already generated a skeleton for this scope type
debug_msg("Initial visit to scope type %s at depth %d",
ivl_scope_tname(scope), depth);
switch (ivl_scope_type(scope)) {
case IVL_SCT_MODULE:
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))
return 0; // Not interested in this instance
if (ivl_scope_type(scope) == IVL_SCT_MODULE) {
vhdl_entity *ent = find_entity(scope);
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);
while (ivl_scope_type(parent) == IVL_SCT_GENERATE)
parent = ivl_scope_parent(scope);
vhdl_entity* ent = find_entity(parent);
assert(ent);
@ -1020,7 +1000,7 @@ extern "C" int draw_functions(ivl_scope_t scope, void *_parent)
{
if (!is_default_scope_instance(scope))
return 0; // Not interested in this instance
ivl_scope_t parent = static_cast<ivl_scope_t>(_parent);
if (ivl_scope_type(scope) == IVL_SCT_FUNCTION) {
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))
return 0; // Not interested in this instance
ivl_scope_children(scope, draw_constant_drivers, scope);
if (ivl_scope_type(scope) == IVL_SCT_MODULE) {
vhdl_entity *ent = find_entity(scope);
assert(ent);
@ -1054,7 +1034,7 @@ extern "C" int draw_constant_drivers(ivl_scope_t scope, void *_parent)
int nsigs = ivl_scope_sigs(scope);
for (int i = 0; i < nsigs; i++) {
ivl_signal_t sig = ivl_scope_sig(scope, i);
for (unsigned j = ivl_signal_array_base(sig);
j < ivl_signal_array_count(sig);
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);
if (!nex) continue; // skip virtual pins
seen_nexus(nex);
nexus_private_t *priv =
static_cast<nexus_private_t*>(ivl_nexus_get_private(nex));
assert(priv);
@ -1072,9 +1052,9 @@ extern "C" int draw_constant_drivers(ivl_scope_t scope, void *_parent)
if (priv->const_driver
&& ivl_signal_port(sig) != IVL_SIP_INPUT) { // Don't drive inputs
assert(j == 0); // TODO: Make work for more words
vhdl_var_ref *ref = nexus_to_var_ref(arch_scope, nex);
ent->get_arch()->add_stmt
(new vhdl_cassign_stmt(ref, priv->const_driver));
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);
// 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();
it != sn->connect.end();
++it) {
@ -1095,20 +1075,20 @@ extern "C" int draw_constant_drivers(ivl_scope_t scope, void *_parent)
vhdl_type* ltype =
vhdl_type::type_for(ivl_signal_width(*it),
ivl_signal_signed(*it));
vhdl_var_ref *rref =
new vhdl_var_ref(get_renamed_signal(sn->sig).c_str(), rtype);
vhdl_var_ref *lref =
new vhdl_var_ref(get_renamed_signal(*it).c_str(), ltype);
// Make sure the LHS and RHS have the same type
vhdl_expr* rhs = rref->cast(lref->get_type());
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))
return 0; // Not interested in this instance
if (ivl_scope_type(scope) == IVL_SCT_MODULE) {
vhdl_entity *ent = find_entity(scope);
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);
}
set_active_entity(NULL);
}
}
return ivl_scope_children(scope, draw_all_logic_and_lpm, scope);
}
extern "C" int draw_hierarchy(ivl_scope_t scope, void *_parent)
{
{
if (ivl_scope_type(scope) == IVL_SCT_MODULE && _parent) {
ivl_scope_t parent = static_cast<ivl_scope_t>(_parent);
// Skip over any containing generate scopes
while (ivl_scope_type(parent) == IVL_SCT_GENERATE)
parent = ivl_scope_parent(parent);
if (!is_default_scope_instance(parent))
return 0; // Not generating code for the parent instance so
// don't generate for the child
vhdl_entity *ent = find_entity(scope);
assert(ent);
vhdl_entity *parent_ent = find_entity(parent);
assert(parent_ent);
vhdl_arch *parent_arch = parent_ent->get_arch();
assert(parent_arch != NULL);
// Create a forward declaration for it
vhdl_scope *parent_scope = parent_arch->get_scope();
if (!parent_scope->have_declared(ent->get_name())) {
vhdl_decl *comp_decl = vhdl_component_decl::component_decl_for(ent);
parent_arch->get_scope()->add_decl(comp_decl);
}
// And an instantiation statement
string inst_name(ivl_scope_basename(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
inst_name += "_inst";
}
// Need to replace any [ and ] characters that result
// from generate statements
string::size_type loc = inst_name.find('[', 0);
if (loc != string::npos)
inst_name.erase(loc, 1);
loc = inst_name.find(']', 0);
if (loc != string::npos)
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
// already declared
avoid_name_collision(inst_name, parent_arch->get_scope());
vhdl_comp_inst *inst =
new vhdl_comp_inst(inst_name.c_str(), ent->get_name().c_str());
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 "
<< ivl_scope_file(scope) << ":" << ivl_scope_lineno(scope);
inst->set_comment(ss.str().c_str());
parent_arch->add_stmt(inst);
}
}
return ivl_scope_children(scope, draw_hierarchy, scope);
}
int draw_scope(ivl_scope_t scope, void *_parent)
{
{
int rc = draw_skeleton_scope(scope, _parent);
if (rc != 0)
return rc;
@ -1225,7 +1205,7 @@ int draw_scope(ivl_scope_t scope, void *_parent)
rc = draw_all_logic_and_lpm(scope, _parent);
if (rc != 0)
return rc;
return rc;
rc = draw_hierarchy(scope, _parent);
if (rc != 0)
@ -1238,7 +1218,7 @@ int draw_scope(ivl_scope_t scope, void *_parent)
rc = draw_constant_drivers(scope, _parent);
if (rc != 0)
return rc;
return 0;
}

View File

@ -25,9 +25,8 @@
#include <algorithm>
#include <string>
#include <map>
#include <vector>
#include <set>
#include <cstring>
#include <iostream>
using namespace std;
@ -54,7 +53,7 @@ using namespace std;
* provides a mechanism for renaming signals -- i.e. when
* an output has the same name as register: valid in Verilog
* but not in VHDL, so two separate signals need to be
* defined.
* defined.
*/
struct signal_defn_t {
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
// entity added will correspond to the first (top) Verilog module
// 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
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;
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
// 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;
// True if signal `sig' has already been encountered by the code
// generator. This means we have already assigned it to a VHDL code
// 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
struct cmp_ent_name {
cmp_ent_name(const string& n) : name_(n) {}
bool operator()(const vhdl_entity* ent) const
{
return ent->get_name() == name_;
@ -156,7 +156,7 @@ struct cmp_ent_name {
// Find an entity given its name.
vhdl_entity* find_entity(const string& name)
{
{
entity_list_t::const_iterator it
= find_if(g_entities.begin(), g_entities.end(),
cmp_ent_name(name));
@ -176,34 +176,21 @@ vhdl_entity* find_entity(ivl_scope_t scope)
// Skip over generate scopes
while (ivl_scope_type(scope) == IVL_SCT_GENERATE)
scope = ivl_scope_parent(scope);
assert(ivl_scope_type(scope) == IVL_SCT_MODULE);
if (is_default_scope_instance(scope)) {
scope_name_map_t::iterator it = g_scope_names.find(scope);
if (it != g_scope_names.end())
return find_entity((*it).second);
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);
}
scope_name_map_t::iterator it = g_scope_names.find(ivl_scope_tname(scope));
if (it != g_scope_names.end())
return find_entity((*it).second);
else
return NULL;
}
}
// Add an entity/architecture pair to the list of entities to emit.
void remember_entity(vhdl_entity* ent, ivl_scope_t scope)
{
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.
@ -226,7 +213,7 @@ void free_all_vhdl_objects()
size_t total = vhdl_element::total_allocated();
debug_msg("%d total bytes used for VHDL syntax objects", total);
g_entities.clear();
}
@ -241,52 +228,12 @@ void set_active_entity(vhdl_entity *ent)
{
g_active_entity = ent;
}
/*
* True if two scopes have the same type name.
*/
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 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;
return strcmp(ivl_scope_tname(a), ivl_scope_tname(b)) == 0;
}
/*
@ -299,7 +246,7 @@ bool seen_this_scope_type(ivl_scope_t s)
if (find_if(g_default_scopes.begin(), g_default_scopes.end(),
bind1st(ptr_fun(same_scope_type_name), s))
== g_default_scopes.end()) {
g_default_scopes.push_back(s);
g_default_scopes.insert(s);
return false;
}
else

View File

@ -1,7 +1,7 @@
/*
* 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
* it under the terms of the GNU General Public License as published by
@ -30,9 +30,6 @@
#include <set>
#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
* 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
* some VHDL simulators and implement the $finish functionality
* 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,
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"));
}
else {
container->add_stmt(
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()));
}
container->add_stmt(new vhdl_assert_stmt("SIMULATION FINISHED"));
}
if (count == 0)
text->add_expr(new vhdl_const_string(""));
container->add_stmt(new vhdl_report_stmt(text));
return 0;
}
@ -172,9 +67,9 @@ static int draw_stask(vhdl_procedural *proc, stmt_container *container,
const char *name = ivl_stmt_name(stmt);
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)
return draw_stask_display(proc, container, stmt);
return draw_stask_display(proc, container, stmt, false);
else if (strcmp(name, "$finish") == 0)
return draw_stask_finish(proc, container, stmt);
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
* 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,
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));
}
}
int count = ivl_stmt_block_count(stmt);
for (int i = 0; i < count; 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;
}
/*
* 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)
{
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 ((base = translate_expr(e_off)) == NULL)
return NULL;
vhdl_type integer(VHDL_TYPE_INTEGER);
base = base->cast(&integer);
}
unsigned lval_width = ivl_lval_width(lval);
string signame(get_renamed_signal(sig));
vhdl_decl *decl = scope->get_decl(signame);
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
decl = shadow_decl;
}
vhdl_type *ltype = new vhdl_type(*decl->get_type());
vhdl_var_ref *lval_ref = new vhdl_var_ref(decl->get_name(), ltype);
if (base) {
@ -305,7 +221,7 @@ static bool assignment_lvals(ivl_statement_t stmt, vhdl_procedural *proc,
return false;
lvals.push_back(lhs);
}
}
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);
case vhdl_decl::ASSIGN_NONBLOCK:
return new vhdl_nbassign_stmt(lhs, rhs);
}
}
assert(false);
return NULL;
}
@ -347,68 +263,12 @@ bool check_valid_assignment(vhdl_decl::assign_type_t atype, vhdl_procedural *pro
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.
// If a statement was generated then `assign_type' will contain the
// type of assignment that was generated; this should be initialised
// to some sensible default.
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)
{
list<vhdl_var_ref*> lvals;
@ -426,23 +286,14 @@ void make_assignment(vhdl_procedural *proc, stmt_container *container,
if (rhs == NULL)
return;
emit_wait_for_0(proc, container, stmt, rhs);
if (rhs2)
emit_wait_for_0(proc, container, stmt, rhs2);
if (lvals.size() == 1) {
vhdl_var_ref *lhs = lvals.front();
rhs = rhs->cast(lhs->get_type());
ivl_expr_t i_delay;
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);
if (after == NULL)
return;
emit_wait_for_0(proc, container, stmt, after);
}
// Find the declaration of the LHS so we know what type
// 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());
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
// if statement (eliminates a function call and produces
// more idiomatic code)
@ -460,13 +308,11 @@ void make_assignment(vhdl_procedural *proc, stmt_container *container,
rhs2 = rhs2->cast(lhs->get_type());
vhdl_var_ref *lhs2 =
make_assign_lhs(ivl_stmt_lval(stmt, 0), proc->get_scope());
vhdl_expr *test = translate_expr(ivl_expr_oper1(rval));
if (NULL == test)
return;
emit_wait_for_0(proc, container, stmt, test);
if (!check_valid_assignment(decl->assignment_type(), proc, stmt))
return;
@ -498,7 +344,7 @@ void make_assignment(vhdl_procedural *proc, stmt_container *container,
// declaration as initialisers. This optimisation is only
// performed on assignments of constant values to prevent
// ordering problems.
// This also has another application: If this is an `initial'
// process and we haven't yet generated a `wait' statement then
// moving the assignment to the initialization preserves the
@ -514,7 +360,7 @@ void make_assignment(vhdl_procedural *proc, stmt_container *container,
&& !decl->has_initial()
&& rhs->constant()
&& decl->get_type()->get_name() != VHDL_TYPE_ARRAY) {
// If this assignment is not in the top-level container
// it will not be made on all paths through the code
// 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
else {
decl->set_initial(rhs);
proc->get_scope()->hoisted_initialiser(true);
delete lhs;
return;
}
@ -534,8 +379,8 @@ void make_assignment(vhdl_procedural *proc, stmt_container *container,
vhdl_abstract_assign_stmt *a =
assign_for(decl->assignment_type(), lhs, rhs);
container->add_stmt(a);
if (after != NULL)
if (after != NULL)
a->set_after(after);
}
else {
@ -551,25 +396,20 @@ void make_assignment(vhdl_procedural *proc, stmt_container *container,
proc->get_scope()->add_decl(tmp_decl);
container->add_stmt(new vhdl_assign_stmt(tmp_decl->make_ref(), rhs));
list<vhdl_var_ref*>::iterator it;
int width_so_far = 0;
for (it = lvals.begin(); it != lvals.end(); ++it) {
vhdl_var_ref *tmp_rhs = tmp_decl->make_ref();
int lval_width = (*it)->get_type()->get_width();
vhdl_expr *slice_base = new vhdl_const_int(width_so_far);
tmp_rhs->set_slice(slice_base, lval_width - 1);
ivl_expr_t i_delay;
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);
if (after == NULL)
return;
emit_wait_for_0(proc, container, stmt, after);
}
// Find the declaration of the LHS so we know what type
// 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))
return;
vhdl_abstract_assign_stmt *a =
assign_for(decl->assignment_type(), *it, tmp_rhs);
if (after)
@ -588,11 +428,10 @@ void make_assignment(vhdl_procedural *proc, stmt_container *container,
container->add_stmt(a);
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)
{
vhdl_decl::assign_type_t assign_type = vhdl_decl::ASSIGN_NONBLOCK;
bool emulate_blocking = proc->get_scope()->allow_signal_assignment();
make_assignment(proc, container, stmt, emulate_blocking, assign_type);
if (proc->get_scope()->allow_signal_assignment()) {
// Blocking assignment is implemented as non-blocking assignment
// 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;
}
@ -646,7 +501,9 @@ static int draw_delay(vhdl_procedural *proc, stmt_container *container,
if (NULL == time)
return 1;
}
prune_wait_for_0(container);
ivl_statement_t sub_stmt = ivl_stmt_sub_stmt(stmt);
vhdl_wait_stmt *wait =
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
// a process it cannot have a sensitivity list
proc->added_wait_stmt();
container->add_stmt(wait);
// Expand the sub-statement as well
@ -662,12 +519,12 @@ static int draw_delay(vhdl_procedural *proc, stmt_container *container,
// is caught here instead
if (ivl_statement_type(sub_stmt) != IVL_ST_NOOP)
draw_stmt(proc, container, sub_stmt);
// Any further assignments occur after simulation time 0
// so they cannot be used to initialise signal declarations
// (if this scope is an initial process)
proc->get_scope()->set_initializing(false);
proc->get_scope()->set_initializing(false);
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
// All other code will fall back on the default draw_wait
// Store a set of the edge triggered signals
// The second item is true if this is positive-edge
set<ivl_nexus_t> edge_triggered;
const int nevents = ivl_stmt_nevent(stmt);
for (int i = 0; i < nevents; i++) {
ivl_event_t event = ivl_stmt_events(stmt, i);
if (ivl_event_nany(event) > 0)
return false;
int npos = ivl_event_npos(event);
for (int j = 0; j < npos; 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());
}
assert(edge);
edge->add_expr(nexus_to_var_ref(proc->get_scope(), *clock_net.begin()));
// Draw the clocked branch
// For an asynchronous reset we just want this around the else branch,
stmt_container *else_container = body->add_elsif(edge);
draw_stmt(proc, else_container, ivl_stmt_cond_false(sub_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
* a sensitivity list may not contain any `wait' statements: we need
* to generate these to accurately model some Verilog statements.
*
*
* The steps followed are:
* 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
@ -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
// first thing inside a process) then we can extract these
// events out into the sensitivity list as long as we haven't
// promoted any preceding assignments to initialisers
bool is_top_level =
container == proc->get_container()
&& container->empty()
&& !proc->get_scope()->hoisted_initialiser();
// events out into the sensitivity list
bool is_top_level = container == proc->get_container()
&& container->empty();
// 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
if (is_top_level && draw_synthesisable_wait(proc, container, stmt))
return 0;
int nevents = ivl_stmt_nevent(stmt);
bool combinatorial = true; // True if no negedge/posedge events
for (int i = 0; i < nevents; 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;
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++) {
ivl_event_t event = ivl_stmt_events(stmt, i);
int nany = ivl_event_nany(event);
for (int j = 0; j < nany; 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;
draw_stmt(proc, &tmp_container, ivl_stmt_sub_stmt(stmt), true);
for (int i = 0; i < nevents; i++) {
ivl_event_t event = ivl_stmt_events(stmt, i);
int nany = ivl_event_nany(event);
for (int j = 0; j < nany; j++) {
ivl_nexus_t nexus = ivl_event_any(event, j);
vhdl_var_ref *ref = nexus_to_var_ref(proc->get_scope(), nexus);
ref->set_name(ref->get_name() + "'Event");
test->add_expr(ref);
if (!proc->contains_wait_stmt() && is_top_level)
proc->add_sensitivity(ref->get_name());
}
int nneg = ivl_event_nneg(event);
for (int j = 0; j < nneg; 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 =
new vhdl_fcall("falling_edge", vhdl_type::boolean());
detect->add_expr(ref);
test->add_expr(detect);
if (!proc->contains_wait_stmt() && is_top_level)
proc->add_sensitivity(ref->get_name());
}
int npos = ivl_event_npos(event);
for (int j = 0; j < npos; 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 =
new vhdl_fcall("rising_edge", vhdl_type::boolean());
detect->add_expr(ref);
test->add_expr(detect);
if (!proc->contains_wait_stmt() && is_top_level)
proc->add_sensitivity(ref->get_name());
}
}
if (proc->contains_wait_stmt() || !is_top_level) {
container->add_stmt(new vhdl_wait_stmt(VHDL_WAIT_UNTIL, test));
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);
}
}
return 0;
}
@ -1022,11 +876,8 @@ static int draw_if(vhdl_procedural *proc, stmt_container *container,
if (NULL == test)
return 1;
emit_wait_for_0(proc, container, 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);
if (cond_true_stmt)
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)
draw_stmt(proc, vhdif->get_else_container(), cond_false_stmt, is_last);
container->add_stmt(vhdif);
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)) {
const char *tmp_name = "Verilog_Case_Ex";
vhdl_type *test_type = new vhdl_type(*test->get_type());
if (!proc->get_scope()->have_declared(tmp_name)) {
proc->get_scope()->add_decl
(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);
if (NULL == test)
return 1;
vhdl_case_stmt *vhdlcase = new vhdl_case_stmt(test);
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
// if there isn't a default one.
bool have_others = false;
int nbranches = ivl_stmt_case_count(stmt);
for (int i = 0; i < nbranches; i++) {
vhdl_expr *when;
@ -1094,7 +947,7 @@ static int draw_case(vhdl_procedural *proc, stmt_container *container,
when = new vhdl_var_ref("others", NULL);
have_others = true;
}
vhdl_case_branch *branch = new vhdl_case_branch(when);
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));
others->get_container()->add_stmt(new vhdl_null_stmt());
vhdlcase->add_branch(others);
}
}
return 0;
}
@ -1472,12 +1325,12 @@ int draw_casezx(vhdl_procedural *proc, stmt_container *container,
return 1;
vhdl_if_stmt *result = NULL;
int nbranches = ivl_stmt_case_count(stmt);
bool is_casez = ivl_statement_type(stmt) == IVL_ST_CASEZ;
for (int i = 0; i < nbranches; i++) {
stmt_container *where = NULL;
ivl_expr_t net = ivl_stmt_case_expr(stmt, i);
if (net) {
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
delete test;
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));
if (rc != 0)
return 1;
vhdl_expr *test = translate_expr(ivl_stmt_cond_expr(stmt));
if (NULL == test)
return 1;
@ -1550,13 +1403,9 @@ int draw_while(vhdl_procedural *proc, stmt_container *container,
vhdl_type boolean(VHDL_TYPE_BOOLEAN);
test = test->cast(&boolean);
emit_wait_for_0(proc, container, stmt, test);
vhdl_while_stmt *loop = new vhdl_while_stmt(test);
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);
return 0;
}
@ -1588,7 +1437,7 @@ int draw_repeat(vhdl_procedural *proc, stmt_container *container,
container->add_stmt(loop);
draw_stmt(proc, loop->get_container(), ivl_stmt_sub_stmt(stmt));
return 0;
}
@ -1606,7 +1455,7 @@ int draw_utask(vhdl_procedural *proc, stmt_container *container,
// TOOD: this completely ignores parameters!
draw_stmt(proc, container, ivl_scope_def(tscope), false);
return 0;
}
@ -1624,7 +1473,7 @@ int draw_stmt(vhdl_procedural *proc, stmt_container *container,
ivl_statement_t stmt, bool is_last)
{
assert(stmt);
switch (ivl_statement_type(stmt)) {
case IVL_ST_STASK:
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)",
ivl_stmt_file(stmt), ivl_stmt_lineno(stmt),
ivl_statement_type(stmt));
return 1;
return 1;
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,7 +1,7 @@
/*
* 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
* it under the terms of the GNU General Public License as published by
@ -31,15 +31,14 @@
using namespace std;
vhdl_scope::vhdl_scope()
: parent_(NULL), init_(false), sig_assign_(true),
hoisted_init_(false)
: parent_(NULL), init_(false), sig_assign_(true)
{
}
vhdl_scope::~vhdl_scope()
{
}
void vhdl_scope::set_initializing(bool i)
@ -101,16 +100,6 @@ vhdl_scope *vhdl_scope::get_parent() const
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__)
: depth(depth__), name_(name), arch_(arch),
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()
{
}
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 << "use ieee.std_logic_1164.all;" << std::endl;
of << "use ieee.numeric_std.all;" << std::endl;
of << "use std.textio.all;" << std::endl;
of << std::endl;
emit_comment(of, level);
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), ";");
of << ");";
}
newline(of, level);
of << "end entity; ";
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)
{
int vhdl_units = std::min(units, precision);
if (vhdl_units >= -3)
time_unit_ = TIME_UNIT_MS;
else if (vhdl_units >= -6)
@ -177,7 +167,7 @@ void vhdl_entity::set_time_units(int units, int precision)
vhdl_arch::~vhdl_arch()
{
}
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;
}
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)
{
sens_.push_back(name);
@ -233,7 +213,7 @@ void vhdl_process::emit(std::ostream &of, int level) const
if (name_.size() > 0)
of << name_ << ": ";
of << "process ";
int num_sens = sens_.size();
if (num_sens > 0) {
of << "(";
@ -255,7 +235,7 @@ void vhdl_process::emit(std::ostream &of, int level) const
stmt_container::~stmt_container()
{
}
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
{
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)
: comp_name_(comp_name), inst_name_(inst_name)
{
}
vhdl_comp_inst::~vhdl_comp_inst()
{
}
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));
of << ")";
}
of << ";";
}
@ -352,7 +332,7 @@ vhdl_component_decl *vhdl_component_decl::component_decl_for(vhdl_entity *ent)
(ent->get_name().c_str());
decl->ports_ = ent->get_scope()->get_decls();
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), ";");
of << ");";
}
newline(of, level);
of << "end component;";
}
vhdl_wait_stmt::~vhdl_wait_stmt()
{
}
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;
}
of << ";";
emit_comment(of, level, true);
}
vhdl_decl::~vhdl_decl()
{
}
// 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)
{
{
if (!has_initial_) {
assert(initial_ == NULL);
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
{
of << name_ << " : ";
switch (mode_) {
case VHDL_PORT_IN:
of << "in ";
@ -466,7 +445,7 @@ void vhdl_port_decl::emit(std::ostream &of, int level) const
of << "buffer ";
break;
}
type_->emit(of, level);
}
@ -490,12 +469,12 @@ void vhdl_var_decl::emit(std::ostream &of, int level) const
{
of << "variable " << name_ << " : ";
type_->emit(of, level);
if (initial_) {
of << " := ";
initial_->emit(of, level);
}
of << ";";
emit_comment(of, level, true);
}
@ -504,12 +483,12 @@ void vhdl_signal_decl::emit(std::ostream &of, int level) const
{
of << "signal " << name_ << " : ";
type_->emit(of, level);
if (initial_) {
of << " := ";
initial_->emit(of, level);
}
of << ";";
emit_comment(of, level, true);
}
@ -523,7 +502,7 @@ void vhdl_type_decl::emit(std::ostream &of, int level) const
vhdl_expr::~vhdl_expr()
{
}
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()
{
}
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
{
of << "(";
int size = exprs_.size();
std::list<vhdl_expr*>::const_iterator 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()
{
}
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_width_ = w;
vhdl_type_name_t tname = type_->get_name();
if (tname == VHDL_TYPE_ARRAY) {
type_ = type_->get_base();
}
else {
assert(tname == VHDL_TYPE_UNSIGNED || tname == VHDL_TYPE_SIGNED);
if (w > 0)
type_ = new vhdl_type(tname, w);
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
{
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
@ -641,13 +624,13 @@ void vhdl_fcall::emit(std::ostream &of, int level) const
vhdl_abstract_assign_stmt::~vhdl_abstract_assign_stmt()
{
}
void vhdl_abstract_assign_stmt::find_vars(vhdl_var_set_t& read,
vhdl_var_set_t& write)
{
lhs_->find_vars(write);
write.insert(lhs_);
rhs_->find_vars(read);
}
@ -661,7 +644,7 @@ void vhdl_nbassign_stmt::emit(std::ostream &of, int level) const
of << " after ";
after_->emit(of, level);
}
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,
bool qualify)
bool qualify)
: vhdl_expr(issigned ? vhdl_type::nsigned(width)
: vhdl_type::nunsigned(width), true),
qualified_(qualify),
signed_(issigned)
{
{
// Can't rely on value being NULL-terminated
while (width--)
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) {
of << "X\"" << hex << setfill('0') << setw(bits / 4) << ival;
}
else {
else {
of << "\"";
std::string::const_reverse_iterator it;
for (it = value_.rbegin(); it != value_.rend(); ++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()
{
}
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 ";
}
rhs_->emit(of, level);
if (after_) {
of << " after ";
after_->emit(of, level);
}
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
{
of << "assert false "; // TODO: Allow arbitrary expression
vhdl_report_stmt::emit(of, level);
of << "assert false"; // TODO: Allow arbitrary expression
of << " report \"" << reason_ << "\" severity failure;";
}
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()
{
}
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
{
emit_comment(of, level);
of << "if ";
test_->emit(of, level);
of << " then";
@ -856,7 +807,7 @@ void vhdl_if_stmt::emit(std::ostream &of, int level) const
of << " then";
(*it).container->emit(of, level);
}
if (!else_part_.empty()) {
of << "else";
else_part_.emit(of, level);
@ -897,7 +848,7 @@ void vhdl_expr::close_parens(std::ostream& of)
vhdl_unaryop_expr::~vhdl_unaryop_expr()
{
}
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()
{
}
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);
assert(operands_.size() > 0);
assert(operands_.size() > 0);
std::list<vhdl_expr*>::const_iterator it = operands_.begin();
(*it)->emit(of, level);
@ -965,14 +916,14 @@ void vhdl_binop_expr::emit(std::ostream &of, int level) const
of << " " << ops[op_] << " ";
(*it)->emit(of, level);
}
}
close_parens(of);
}
vhdl_bit_spec_expr::~vhdl_bit_spec_expr()
{
}
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
{
of << "(";
std::list<bit_map>::const_iterator it;
it = bits_.begin();
while (it != bits_.end()) {
@ -998,13 +949,13 @@ void vhdl_bit_spec_expr::emit(std::ostream &of, int level) const
of << (bits_.empty() ? "" : ", ") << "others => ";
others_->emit(of, level);
}
of << ")";
}
vhdl_case_branch::~vhdl_case_branch()
{
}
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()
{
}
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
newline(of, level);
}
of << "end case;";
}
vhdl_while_stmt::~vhdl_while_stmt()
{
}
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()
{
}
@ -1156,7 +1107,7 @@ void vhdl_param_decl::emit(std::ostream &of, int level) const
vhdl_with_select_stmt::~vhdl_with_select_stmt()
{
}
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 ";
test_->emit(of, level);
of << " select";
emit_comment(of, level, true);
emit_comment(of, level, true);
newline(of, indent(level));
out_->emit(of, level);
of << " <= ";
of << " <= ";
when_list_t::const_iterator it = whens_.begin();
while (it != whens_.end()) {
(*it).value->emit(of, level);
@ -1179,7 +1130,7 @@ void vhdl_with_select_stmt::emit(std::ostream &of, int level) const
}
of << " when ";
(*it).cond->emit(of, level);
if (++it != whens_.end() || others_ != NULL) {
of << ",";
newline(of, indent(level));

View File

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

View File

@ -1,4 +1,3 @@
// -*- mode: c++ -*-
#ifndef 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* readable_ref(vhdl_scope* scope, ivl_nexus_t nex);
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);
#endif /* #ifndef INC_VHDL_TARGET_H */

View File

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

View File

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

View File

@ -105,12 +105,13 @@ static void draw_lpm_mux_ab(ivl_lpm_t net, const char*muxz)
static void draw_lpm_mux_nest(ivl_lpm_t net, const char*muxz)
{
int idx, level;
unsigned idx, level;
unsigned width = ivl_lpm_width(net);
unsigned swidth = ivl_lpm_selects(net);
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)));

View File

@ -94,7 +94,8 @@ static char* draw_C4_to_string(ivl_net_const_t cptr)
for (idx = 0 ; idx < ivl_const_width(cptr) ; idx += 1) {
char bitchar = bits[ivl_const_width(cptr)-idx-1];
*dp++ = bitchar;
assert((dp - result) < result_len);
assert(dp >= result);
assert((unsigned)(dp - result) < result_len);
}
strcpy(dp, ">");
@ -144,7 +145,8 @@ static char* draw_C8_to_string(ivl_net_const_t cptr,
assert(0);
break;
}
assert(dp - result < nresult);
assert(dp >= result);
assert((unsigned)(dp - result) < nresult);
}
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++ = '>';
*dp = 0;
assert((dp-result) <= result_len);
assert(dp >= result);
assert((unsigned)(dp - result) <= result_len);
return result;
} else {
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++ = '>';
*dp = 0;
assert((dp-result) <= result_len);
assert(dp >= result);
assert((unsigned)(dp - result) <= result_len);
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++ = '>';
*dp = 0;
assert((dp-result) <= result_len);
assert(dp >= result);
assert((unsigned)(dp - result) <= result_len);
} else {
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++ = '>';
*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 (ndrivers > 1) {
unsigned uidx;
ivl_signal_t usig;
ivl_signal_t usig = 0;
/* Find the uwire signal. */
for (uidx = 0 ; uidx < ivl_nexus_ptrs(nex) ; uidx += 1) {
ivl_nexus_ptr_t ptr = ivl_nexus_ptr(nex, uidx);

View File

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

View File

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

View File

@ -929,9 +929,9 @@ static struct vector_info draw_binary_expr_le(ivl_expr_t expr,
case 'G':
rv = draw_eval_expr_wid(re, owid, STUFF_OK_XZ);
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);
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);
} else {
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':
lv = draw_eval_expr_wid(le, owid, STUFF_OK_XZ);
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);
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);
} else {
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 '<':
lv = draw_eval_expr_wid(le, owid, STUFF_OK_XZ);
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);
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);
} else {
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 '>':
rv = draw_eval_expr_wid(re, owid, STUFF_OK_XZ);
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);
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);
} else {
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
* 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.
*/
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. */
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. */
if (subv.base < 4) {
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",
res.base, subv.base, subv.wid);
if (ivl_expr_signed(sube)) {
int idx;
unsigned idx;
for (idx = subv.wid ; idx < res.wid ; idx += 1) {
fprintf(vvp_out, " %%mov %u, %u, 1;\n",
res.base+idx, subv.base+subv.wid-1);

View File

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

View File

@ -28,7 +28,7 @@
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_scope_t path_scope = ivl_path_scope(path);

View File

@ -260,9 +260,43 @@ const char*drive_string(ivl_drive_t drive)
* on. The last net is selected as the output of the nexus.
*/
/*
* 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
* 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
* 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)
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;
}
@ -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
the functor that I create later. */
ninp = ivl_logic_pins(lptr) - 1;
assert(ninp >= 0);
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));
level = 0;
while (ninp) {
int inst;
for (inst = 0; inst < ninp; inst += 4) {
unsigned inst;
for (inst = 0; inst < (unsigned)ninp; inst += 4) {
if (ninp > 4)
fprintf(vvp_out, "L_%p/%d/%d .functor %s %u",
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);
}
for (pdx = inst; pdx < ninp && pdx < inst+4 ; pdx += 1) {
for (pdx = inst; pdx < (unsigned)ninp && pdx < inst+4 ; pdx += 1) {
if (level) {
fprintf(vvp_out, ", L_%p/%d/%d",
lptr, level - 1, pdx*4);

View File

@ -42,6 +42,10 @@
#define FST_MACOSX
#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)
{
uint64_t nxt;
unsigned char buf[32];
unsigned char buf[10]; /* ceil(64/7) = 10 */
unsigned char *pnt = buf;
int len;
@ -391,6 +395,50 @@ fstFwrite(buf, len, 1, handle);
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))
{
uint32_t prev_chg;
uint32_t fpos;
uint32_t *vm4ip;
@ -1573,14 +1620,15 @@ if((xc) && (handle <= xc->maxhandle))
if(!xc->is_initial_time)
{
prev_chg = vm4ip[2];
fpos = xc->vchn_siz;
fstFwrite(&prev_chg, 1, sizeof(uint32_t), xc->vchn_handle);
xc->vchn_siz += 4;
xc->vchn_siz += fstWriterVarint(xc->vchn_handle, xc->tchn_idx - vm4ip[3]);
fstFwrite(buf, len, 1, xc->vchn_handle);
xc->vchn_siz += len;
/* cygwin runs faster if these writes are combined, so the new fstWriterUint32WithVarint function, but should help with regular */
#ifndef FST_USE_FWRITE_COMBINING
xc->vchn_siz += fstWriterUint32WithVarint(xc->vchn_handle, &vm4ip[2], xc->tchn_idx - vm4ip[3]); /* prev_chg is vm4ip[2] */
fstFwrite(buf, len, 1, xc->vchn_handle);
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[2] = fpos;
}

View File

@ -265,7 +265,8 @@ static unsigned int get_format_char(char **rtn, int ljust, int plus,
unsigned int ini_size = 512; /* The initial size of the buffer. */
/* 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. */
result = malloc(ini_size*sizeof(char));

View File

@ -545,7 +545,7 @@ static unsigned fread_word(FILE *fp, vpiHandle word,
* my local vector. */
val.format = vpiVectorVal;
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].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));
bpe = (width+7)/8;
assert(count >= 0);
if (is_mem) {
unsigned idx;
rtn = 0;
for (idx = 0; idx < count; idx += 1) {
for (idx = 0; idx < (unsigned)count; idx += 1) {
vpiHandle word;
word = vpi_handle_by_index(mem_reg, start+(signed)idx);
rtn += fread_word(fp, word, words, bpe, vector);

View File

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

View File

@ -59,7 +59,7 @@ all: dep vvp@EXEEXT@ libvpi.a vvp.man
clean:
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
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' > $@
tail -n +2 $(srcdir)/vvp.man.in >> $@
vvp.pdf: vvp.man
$(MAN) -t $(srcdir)/vvp.man | $(PS2PDF) - vvp.pdf
vvp.ps: vvp.man
$(MAN) -t ./vvp.man > vvp.ps
vvp.pdf: vvp.ps
$(PS2PDF) vvp.ps vvp.pdf
ifeq (@MINGW32@,yes)
ifeq ($(MAN),none)

View File

@ -769,7 +769,7 @@ static unsigned vpi_array_is_real(vvp_array_t arr)
assert(arr->array_count > 0);
struct __vpiRealVar*rsig = vpip_realvar_from_handle(arr->nets[0]);
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);
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)
{
struct __vpiArray*arr = ARRAY_HANDLE(obj);
cb->extra_data = -1; // This is a callback for every element.
cb->next = arr->vpi_callbacks;

View File

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

View File

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

View File

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

View File

@ -2,7 +2,7 @@
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;
.thread T0;
:file_names 2;

View File

@ -373,7 +373,7 @@ register to read the repetition count from (signed or unsigned).
%evctl/i sets the repetition to an immediate unsigned value.
%evctl/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
that this information has been cleared. You can get an assert if
this information is not managed correctly.

View File

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

View File

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

View File

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

View File

@ -972,7 +972,7 @@ bool of_ASSIGN_V0(vthread_t thr, vvp_code_t cp)
vvp_net_ptr_t ptr (cp->net, 0);
if (bit >= 4) {
// 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);
} else {
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]);
}
// 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,
// and if the difference comes out negative, then adjust.

View File

@ -291,7 +291,7 @@ vvp_island* compile_find_island(const char*island)
*
* The <src> is a label in the domain outside the island, and the
* <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
* that this port represents, because the island will resolve internal
* drivers with the external driver and make the output available on

View File

@ -1212,7 +1212,7 @@ void vvp_vector4_t::mov(unsigned dst, unsigned src, unsigned cnt)
// Here we know that either the source or
// 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 tmp;
@ -1870,8 +1870,8 @@ void vvp_vector4array_aa::reset_instance(vvp_context_t context)
for (unsigned idx = 0 ; idx < words_ ; idx += 1) {
if (cell->abits_ptr_) {
for (unsigned n = 0 ; n < cnt ; n += 1) {
cell->abits_ptr_[n] = vvp_vector4_t::WORD_X_ABITS;
cell->bbits_ptr_[n] = vvp_vector4_t::WORD_X_BBITS;
cell->abits_ptr_[n] = vvp_vector4_t::WORD_X_ABITS;
cell->bbits_ptr_[n] = vvp_vector4_t::WORD_X_BBITS;
}
}
cell++;

View File

@ -65,7 +65,6 @@ typedef void*vvp_context_item_t;
inline vvp_context_t vvp_allocate_context(unsigned nitem)
{
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;
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_;
else
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
// method returns REPL and the caller should propagate the rep
// 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.
virtual prop_t filter_vec4(const vvp_vector4_t&bit, vvp_vector4_t&rep,
unsigned base, unsigned vwid);
@ -1185,7 +1184,7 @@ class vvp_net_fil_t : public vvp_vpi_callback {
virtual unsigned filter_size() const =0;
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
// for the filter.
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
// 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.
template <class T> prop_t filter_input_mask_(const T&val, const T&force, T&rep) const;

View File

@ -91,7 +91,7 @@ class vvp_fun_signal_base : public vvp_net_fun_t {
/*
* Variables and wires can have their values accessed, so this base
* class offers the unified concept of an acessible value.
* class offers the unified concept of an accessible value.
*/
class vvp_signal_value {
public:
@ -280,7 +280,7 @@ class vvp_wire_vec4 : public vvp_wire_base {
vvp_wire_vec4(unsigned wid, vvp_bit4_t init);
// 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
// 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,

View File

@ -394,7 +394,7 @@ static void __compile_real_net2(vvp_net_t*node, vvp_array_t array,
obj = vpip_make_real_var(name, node);
compile_vpi_symbol(my_label, obj);
}
// 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
// must fix the code generator to not rely on the label of the