mirror of
https://github.com/steveicarus/iverilog.git
synced 2026-08-25 07:16:52 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
54c7ef72cb | ||
|
|
50800fd3a1 | ||
|
|
fc0695beb6 | ||
|
|
00891db0d2 | ||
|
|
898b0e0365 | ||
|
|
382c4d74fd | ||
|
|
5bcf083662 | ||
|
|
1bd530c144 | ||
|
|
82a85131a8 | ||
|
|
49b65e86fe | ||
|
|
06d6ac4b33 | ||
|
|
2037650080 | ||
|
|
61f3a84557 | ||
|
|
ed70db84ce | ||
|
|
5348ac14a5 | ||
|
|
aab6fefd8a | ||
|
|
1b8e2a17c7 | ||
|
|
33a391cb71 | ||
|
|
bcc08112aa | ||
|
|
80f30be9d0 | ||
|
|
71faebd6df | ||
|
|
53ae1f29c9 | ||
|
|
857b3e15b6 | ||
|
|
019d61f633 | ||
|
|
d37b6599f4 | ||
|
|
68e52ce6b7 | ||
|
|
4c885f65e1 | ||
|
|
f0e114d59f | ||
|
|
aaaa042f73 | ||
|
|
044da54b41 | ||
|
|
a8b86ea3bb | ||
|
|
e98aad1e9b | ||
|
|
1ef91f800f | ||
|
|
a19efe181b | ||
|
|
81bfbd1549 | ||
|
|
dc2898cc73 | ||
|
|
0c9fb766b6 | ||
|
|
10f8c66f4a | ||
|
|
56f70ec702 | ||
|
|
949054e000 | ||
|
|
47b72c3b74 | ||
|
|
a2c036d5ab | ||
|
|
0d17e57656 | ||
|
|
fd94268315 | ||
|
|
36039e13ec | ||
|
|
a702f99c04 | ||
|
|
4493e3f928 | ||
|
|
3727052000 | ||
|
|
39ff233cf1 | ||
|
|
58118bddc5 | ||
|
|
c2ff3d501c | ||
|
|
46d86ad276 | ||
|
|
4dd1308eb0 | ||
|
|
a978bb1e14 | ||
|
|
707af782b3 | ||
|
|
fc5cf55400 | ||
|
|
6a74a090f0 | ||
|
|
c448b75f2c |
+2
-4
@@ -16,7 +16,7 @@
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.175 2006/04/10 00:37:42 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.176 2006/05/01 20:47:29 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
@@ -161,10 +161,8 @@ lexor.o: lexor.cc parse.h
|
||||
|
||||
parse.o: parse.cc
|
||||
|
||||
parse.cc: $(srcdir)/parse.y
|
||||
parse.cc parse.h: $(srcdir)/parse.y
|
||||
$(YACC) --verbose -t -p VL -d -o parse.cc $(srcdir)/parse.y
|
||||
|
||||
parse.h: parse.cc
|
||||
mv parse.cc.h parse.h 2>/dev/null || mv parse.hh parse.h
|
||||
|
||||
syn-rules.cc: $(srcdir)/syn-rules.y
|
||||
|
||||
+16
-2
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PDelays.cc,v 1.13 2006/01/03 05:22:14 steve Exp $"
|
||||
#ident "$Id: PDelays.cc,v 1.15 2006/07/08 21:48:46 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -65,7 +65,7 @@ void PDelays::set_delays(const svector<PExpr*>*del, bool df)
|
||||
static NetExpr*calculate_val(Design*des, NetScope*scope, const PExpr*expr)
|
||||
{
|
||||
|
||||
NetExpr*dex = expr->elaborate_expr(des, scope);
|
||||
NetExpr*dex = expr->elaborate_expr(des, scope, -1, false);
|
||||
if (NetExpr*tmp = dex->eval_tree()) {
|
||||
delete dex;
|
||||
dex = tmp;
|
||||
@@ -115,6 +115,12 @@ static NetExpr* make_delay_nets(Design*des, NetExpr*expr)
|
||||
return expr;
|
||||
|
||||
NetNet*sig = expr->synthesize(des);
|
||||
if (sig == 0) {
|
||||
cerr << expr->get_line() << ": error: Expression " << *expr
|
||||
<< " is not suitable for delay expression." << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
expr = new NetESignal(sig);
|
||||
return expr;
|
||||
}
|
||||
@@ -163,6 +169,14 @@ void PDelays::eval_delays(Design*des, NetScope*scope,
|
||||
|
||||
/*
|
||||
* $Log: PDelays.cc,v $
|
||||
* Revision 1.15 2006/07/08 21:48:46 steve
|
||||
* Handle real valued literals in net contexts.
|
||||
*
|
||||
* Revision 1.14 2006/06/02 04:48:49 steve
|
||||
* Make elaborate_expr methods aware of the width that the context
|
||||
* requires of it. In the process, fix sizing of the width of unary
|
||||
* minus is context determined sizes.
|
||||
*
|
||||
* Revision 1.13 2006/01/03 05:22:14 steve
|
||||
* Handle complex net node delays.
|
||||
*
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PExpr.h,v 1.78 2006/03/25 02:36:26 steve Exp $"
|
||||
#ident "$Id: PExpr.h,v 1.83 2006/06/18 04:15:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <string>
|
||||
@@ -51,11 +51,13 @@ class PExpr : public LineInfo {
|
||||
|
||||
virtual void dump(ostream&) const;
|
||||
|
||||
// Procedural elaboration of the expression. Set the
|
||||
// bare_memory_ok flag if the result is allowed to be a
|
||||
// NetEMemory without an index.
|
||||
// Procedural elaboration of the expression. The expr_width is
|
||||
// the width of the context of the expression (i.e. the
|
||||
// l-value width of an assignment) or -1 if the expression is
|
||||
// self-determinted. The sys_task_arg flag is true if
|
||||
// expressions are allowed to be incomplete.
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
|
||||
bool sys_task_arg =false) const;
|
||||
int expr_width, bool sys_task_arg) const;
|
||||
|
||||
// Elaborate expressions that are the r-value of parameter
|
||||
// assignments. This elaboration follows the restrictions of
|
||||
@@ -128,6 +130,7 @@ class PEConcat : public PExpr {
|
||||
|
||||
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope,
|
||||
bool implicit_net_ok =false) const;
|
||||
virtual NetNet* elaborate_bi_net(Design*des, NetScope*scope) const;
|
||||
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
|
||||
unsigned width,
|
||||
const NetExpr* rise,
|
||||
@@ -136,13 +139,17 @@ class PEConcat : public PExpr {
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
|
||||
bool sys_task_arg =false) const;
|
||||
int expr_width, bool sys_task_arg) const;
|
||||
virtual NetEConcat*elaborate_pexpr(Design*des, NetScope*) const;
|
||||
virtual NetAssign_* elaborate_lval(Design*des,
|
||||
NetScope*scope,
|
||||
bool is_force) const;
|
||||
virtual bool is_constant(Module*) const;
|
||||
|
||||
private:
|
||||
NetNet* elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||
bool implicit_net_ok,
|
||||
bool bidirectional_flag) const;
|
||||
private:
|
||||
svector<PExpr*>parms_;
|
||||
PExpr*repeat_;
|
||||
@@ -195,7 +202,7 @@ class PEFNumber : public PExpr {
|
||||
virtual bool is_constant(Module*) const;
|
||||
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
|
||||
bool sys_task_arg =false) const;
|
||||
int expr_width, bool sys_task_arg) const;
|
||||
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
|
||||
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
|
||||
@@ -241,7 +248,7 @@ class PEIdent : public PExpr {
|
||||
Link::strength_t drive1) const;
|
||||
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
|
||||
bool sys_task_arg =false) const;
|
||||
int expr_width, bool sys_task_arg) const;
|
||||
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
|
||||
// Elaborate the PEIdent as a port to a module. This method
|
||||
@@ -253,6 +260,11 @@ class PEIdent : public PExpr {
|
||||
|
||||
const hname_t& path() const;
|
||||
|
||||
private:
|
||||
NetAssign_*elaborate_lval_net_part_(Design*, NetScope*, NetNet*) const;
|
||||
NetAssign_*elaborate_lval_net_idx_up_(Design*, NetScope*, NetNet*) const;
|
||||
NetAssign_*elaborate_lval_net_idx_do_(Design*, NetScope*, NetNet*) const;
|
||||
|
||||
private:
|
||||
NetExpr*elaborate_expr_param(Design*des,
|
||||
NetScope*scope,
|
||||
@@ -340,7 +352,7 @@ class PENumber : public PExpr {
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
virtual NetEConst*elaborate_expr(Design*des, NetScope*,
|
||||
bool sys_task_arg =false) const;
|
||||
int expr_width, bool) const;
|
||||
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
virtual NetAssign_* elaborate_lval(Design*des,
|
||||
NetScope*scope,
|
||||
@@ -378,7 +390,7 @@ class PEString : public PExpr {
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
virtual NetEConst*elaborate_expr(Design*des, NetScope*,
|
||||
bool sys_task_arg =false) const;
|
||||
int expr_width, bool) const;
|
||||
virtual NetEConst*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
verinum* eval_const(const Design*, NetScope*) const;
|
||||
|
||||
@@ -403,7 +415,7 @@ class PEUnary : public PExpr {
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
|
||||
bool sys_task_arg =false) const;
|
||||
int expr_width, bool sys_task_arg) const;
|
||||
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
virtual verinum* eval_const(const Design*des, NetScope*sc) const;
|
||||
|
||||
@@ -431,7 +443,7 @@ class PEBinary : public PExpr {
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
virtual NetEBinary*elaborate_expr(Design*des, NetScope*,
|
||||
bool sys_task_arg =false) const;
|
||||
int expr_width, bool sys_task_arg) const;
|
||||
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
virtual verinum* eval_const(const Design*des, NetScope*sc) const;
|
||||
|
||||
@@ -505,7 +517,7 @@ class PETernary : public PExpr {
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
virtual NetETernary*elaborate_expr(Design*des, NetScope*,
|
||||
bool sys_task_arg =false) const;
|
||||
int expr_width, bool sys_task_arg) const;
|
||||
virtual NetETernary*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
virtual verinum* eval_const(const Design*des, NetScope*sc) const;
|
||||
|
||||
@@ -535,7 +547,7 @@ class PECallFunction : public PExpr {
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
|
||||
bool sys_task_arg =false) const;
|
||||
int expr_wid, bool sys_task_arg) const;
|
||||
|
||||
private:
|
||||
hname_t path_;
|
||||
@@ -544,10 +556,34 @@ class PECallFunction : public PExpr {
|
||||
bool check_call_matches_definition_(Design*des, NetScope*dscope) const;
|
||||
|
||||
NetExpr* elaborate_sfunc_(Design*des, NetScope*scope) const;
|
||||
NetNet* elaborate_net_sfunc_(Design*des, NetScope*scope,
|
||||
unsigned width,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
};
|
||||
|
||||
/*
|
||||
* $Log: PExpr.h,v $
|
||||
* Revision 1.83 2006/06/18 04:15:50 steve
|
||||
* Add support for system functions in continuous assignments.
|
||||
*
|
||||
* Revision 1.82 2006/06/02 04:48:49 steve
|
||||
* Make elaborate_expr methods aware of the width that the context
|
||||
* requires of it. In the process, fix sizing of the width of unary
|
||||
* minus is context determined sizes.
|
||||
*
|
||||
* Revision 1.81 2006/04/28 04:28:35 steve
|
||||
* Allow concatenations as arguments to inout ports.
|
||||
*
|
||||
* Revision 1.80 2006/04/16 00:54:04 steve
|
||||
* Cleanup lval part select handling.
|
||||
*
|
||||
* Revision 1.79 2006/04/16 00:15:43 steve
|
||||
* Fix part selects in l-values.
|
||||
*
|
||||
* Revision 1.78 2006/03/25 02:36:26 steve
|
||||
* Get rid of excess PESTring:: prefix within class declaration.
|
||||
*
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@
|
||||
echo "Autoconf in root..."
|
||||
autoconf
|
||||
|
||||
for dir in vpip vpi vvp tgt-vvp tgt-fpga libveriuser cadpli
|
||||
for dir in vpip vpi vvp tgt-vvp tgt-fpga tgt-stub libveriuser cadpli
|
||||
do
|
||||
echo "Autoconf in $dir..."
|
||||
( cd ./$dir ; autoconf --include=.. )
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: cprop.cc,v 1.54 2005/07/15 19:22:52 steve Exp $"
|
||||
#ident "$Id: cprop.cc,v 1.55 2006/05/24 04:32:57 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -738,6 +738,48 @@ v }
|
||||
}
|
||||
}
|
||||
|
||||
static void replace_with_bufif(Design*des, NetMux*obj, NetLogic::TYPE type)
|
||||
{
|
||||
NetScope*scope = obj->scope();
|
||||
NetLogic*tmp = new NetLogic(obj->scope(),
|
||||
scope->local_symbol(),
|
||||
3, type, obj->width());
|
||||
|
||||
des->add_node(tmp);
|
||||
|
||||
connect(obj->pin_Result(), tmp->pin(0));
|
||||
connect(obj->pin_Data(type==NetLogic::BUFIF0? 0 : 1), tmp->pin(1));
|
||||
|
||||
if (obj->width() == 1) {
|
||||
/* Special case that the expression is 1 bit
|
||||
wide. Connect the select directly to the enable. */
|
||||
connect(obj->pin_Sel(), tmp->pin(2));
|
||||
|
||||
} else {
|
||||
/* General case that the expression is arbitrarily
|
||||
wide. Replicate the enable signal (which we
|
||||
assume is 1 bit wide) to match the expression,
|
||||
and connect the enable vector to the enable
|
||||
input of the gate. */
|
||||
NetReplicate*rtmp = new NetReplicate(scope,
|
||||
scope->local_symbol(),
|
||||
obj->width(),
|
||||
obj->width());
|
||||
des->add_node(rtmp);
|
||||
|
||||
connect(obj->pin_Sel(), rtmp->pin(1));
|
||||
connect(tmp->pin(2), rtmp->pin(0));
|
||||
|
||||
NetNet*rsig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, obj->width());
|
||||
rsig->local_flag(true);
|
||||
rsig->data_type(IVL_VT_LOGIC);
|
||||
connect(tmp->pin(2), rsig->pin(0));
|
||||
}
|
||||
|
||||
delete obj;
|
||||
}
|
||||
|
||||
/*
|
||||
* This detects the case where the mux selects between a value and
|
||||
* Vz. In this case, replace the device with a bufif with the sel
|
||||
@@ -764,47 +806,8 @@ void cprop_functor::lpm_mux(Design*des, NetMux*obj)
|
||||
}
|
||||
|
||||
if (flag) {
|
||||
NetScope*scope = obj->scope();
|
||||
NetLogic*tmp = new NetLogic(obj->scope(),
|
||||
scope->local_symbol(),
|
||||
3, NetLogic::BUFIF1, obj->width());
|
||||
|
||||
des->add_node(tmp);
|
||||
|
||||
connect(obj->pin_Result(), tmp->pin(0));
|
||||
connect(obj->pin_Data(1), tmp->pin(1));
|
||||
|
||||
if (obj->width() == 1) {
|
||||
/* Special case that the expression is 1 bit
|
||||
wide. Connect the select directly to the
|
||||
enable. */
|
||||
connect(obj->pin_Sel(), tmp->pin(2));
|
||||
|
||||
} else {
|
||||
/* General case that the expression is arbitrarily
|
||||
wide. Replicate the enable signal (which we
|
||||
assume is 1 bit wide) to match the expression,
|
||||
and connect the enable vector to the enable
|
||||
input of the gate. */
|
||||
NetReplicate*rtmp = new NetReplicate(scope,
|
||||
scope->local_symbol(),
|
||||
obj->width(),
|
||||
obj->width());
|
||||
des->add_node(rtmp);
|
||||
|
||||
|
||||
connect(obj->pin_Sel(), rtmp->pin(1));
|
||||
connect(tmp->pin(2), rtmp->pin(0));
|
||||
|
||||
NetNet*rsig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, obj->width());
|
||||
rsig->local_flag(true);
|
||||
rsig->data_type(IVL_VT_LOGIC);
|
||||
connect(tmp->pin(2), rsig->pin(0));
|
||||
}
|
||||
|
||||
replace_with_bufif(des, obj, NetLogic::BUFIF1);
|
||||
count += 1;
|
||||
delete obj;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -821,19 +824,8 @@ void cprop_functor::lpm_mux(Design*des, NetMux*obj)
|
||||
}
|
||||
|
||||
if (flag) {
|
||||
NetScope*scope = obj->scope();
|
||||
|
||||
NetLogic*tmp = new NetLogic(obj->scope(),
|
||||
scope->local_symbol(),
|
||||
3, NetLogic::BUFIF0, obj->width());
|
||||
|
||||
connect(obj->pin_Result(), tmp->pin(0));
|
||||
connect(obj->pin_Data(0), tmp->pin(1));
|
||||
connect(obj->pin_Sel(), tmp->pin(2));
|
||||
des->add_node(tmp);
|
||||
|
||||
replace_with_bufif(des, obj, NetLogic::BUFIF0);
|
||||
count += 1;
|
||||
delete obj;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -956,6 +948,9 @@ void cprop(Design*des)
|
||||
|
||||
/*
|
||||
* $Log: cprop.cc,v $
|
||||
* Revision 1.55 2006/05/24 04:32:57 steve
|
||||
* Fix handling of ternary-to-bufif0 constant propagation.
|
||||
*
|
||||
* Revision 1.54 2005/07/15 19:22:52 steve
|
||||
* bufif enable is LOGIC.
|
||||
*
|
||||
|
||||
+18
-2
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: design_dump.cc,v 1.165 2006/04/10 00:37:42 steve Exp $"
|
||||
#ident "$Id: design_dump.cc,v 1.167 2006/07/31 03:50:17 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -29,7 +29,7 @@
|
||||
# include <iostream>
|
||||
# include <iomanip>
|
||||
# include "netlist.h"
|
||||
|
||||
# include "compiler.h"
|
||||
|
||||
static ostream& operator<< (ostream&o, NetBlock::Type t)
|
||||
{
|
||||
@@ -462,6 +462,13 @@ void NetUReduce::dump_node(ostream&o, unsigned ind) const
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetSysFunc::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << def_->name << "(...)" << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetUserFunc::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << def_->name() << "(";
|
||||
@@ -984,6 +991,9 @@ void NetEBinary::dump(ostream&o) const
|
||||
case 'O':
|
||||
o << "~|";
|
||||
break;
|
||||
case 'p':
|
||||
o << "**";
|
||||
break;
|
||||
case 'r':
|
||||
o << ">>";
|
||||
break;
|
||||
@@ -1173,6 +1183,12 @@ void Design::dump(ostream&o) const
|
||||
|
||||
/*
|
||||
* $Log: design_dump.cc,v $
|
||||
* Revision 1.167 2006/07/31 03:50:17 steve
|
||||
* Add support for power in constant expressions.
|
||||
*
|
||||
* Revision 1.166 2006/06/18 04:15:50 steve
|
||||
* Add support for system functions in continuous assignments.
|
||||
*
|
||||
* Revision 1.165 2006/04/10 00:37:42 steve
|
||||
* Add support for generate loops w/ wires and gates.
|
||||
*
|
||||
|
||||
+40
-48
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: main.c,v 1.67 2005/07/14 23:38:44 steve Exp $"
|
||||
#ident "$Id: main.c,v 1.69 2006/07/26 00:11:40 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -111,8 +111,6 @@ const char*generation = "2x";
|
||||
|
||||
char warning_flags[16] = "";
|
||||
|
||||
char*inc_list = 0;
|
||||
char*def_list = 0;
|
||||
char*mod_list = 0;
|
||||
char*command_filename = 0;
|
||||
|
||||
@@ -123,6 +121,9 @@ char*source_path = 0;
|
||||
FILE*source_file = 0;
|
||||
unsigned source_count = 0;
|
||||
|
||||
char*defines_path = 0;
|
||||
FILE*defines_file = 0;
|
||||
|
||||
char*iconfig_path = 0;
|
||||
FILE*iconfig_file = 0;
|
||||
|
||||
@@ -269,8 +270,11 @@ static int t_default(char*cmd, unsigned ncmd)
|
||||
|
||||
rc = system(cmd);
|
||||
remove(source_path);
|
||||
if ( ! getenv("IVERILOG_ICONFIG"))
|
||||
if ( ! getenv("IVERILOG_ICONFIG")) {
|
||||
remove(iconfig_path);
|
||||
remove(defines_path);
|
||||
}
|
||||
|
||||
if (rc != 0) {
|
||||
if (rc == 127) {
|
||||
fprintf(stderr, "Failed to execute: %s\n", cmd);
|
||||
@@ -340,32 +344,12 @@ void process_library2_switch(const char *name)
|
||||
|
||||
void process_include_dir(const char *name)
|
||||
{
|
||||
if (inc_list == 0) {
|
||||
inc_list = malloc(strlen(" -I")+strlen(name)+1);
|
||||
strcpy(inc_list, " -I");
|
||||
strcat(inc_list, name);
|
||||
} else {
|
||||
inc_list = realloc(inc_list, strlen(inc_list)
|
||||
+ strlen(" -I")
|
||||
+ strlen(name) + 1);
|
||||
strcat(inc_list, " -I");
|
||||
strcat(inc_list, name);
|
||||
}
|
||||
fprintf(defines_file, "I:%s\n", name);
|
||||
}
|
||||
|
||||
void process_define(const char*name)
|
||||
{
|
||||
if (def_list == 0) {
|
||||
def_list = malloc(strlen(" -D")+strlen(name)+1);
|
||||
strcpy(def_list, " -D");
|
||||
strcat(def_list, name);
|
||||
} else {
|
||||
def_list = realloc(def_list, strlen(def_list)
|
||||
+ strlen(" -D")
|
||||
+ strlen(name) + 1);
|
||||
strcat(def_list, " -D");
|
||||
strcat(def_list, name);
|
||||
}
|
||||
fprintf(defines_file,"D:%s\n", name);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -465,6 +449,19 @@ int main(int argc, char **argv)
|
||||
return 1;
|
||||
}
|
||||
|
||||
defines_path = strdup(my_tempfile("ivrlg2", &defines_file));
|
||||
if (NULL == defines_file) {
|
||||
fprintf(stderr, "%s: Error opening temporary file %s\n",
|
||||
argv[0], defines_path);
|
||||
fprintf(stderr, "%s: Please check TMP or TMPDIR.\n", argv[0]);
|
||||
|
||||
fclose(source_file);
|
||||
remove(source_path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
fprintf(defines_file, "D:__ICARUS__=1\n");
|
||||
|
||||
/* Create another temporary file for passing configuration
|
||||
information to ivl. */
|
||||
|
||||
@@ -485,6 +482,9 @@ int main(int argc, char **argv)
|
||||
fprintf(stderr, "%s: Please check TMP or TMPDIR.\n", argv[0]);
|
||||
fclose(source_file);
|
||||
remove(source_path);
|
||||
|
||||
fclose(defines_file);
|
||||
remove(defines_path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -647,6 +647,9 @@ int main(int argc, char **argv)
|
||||
fclose(source_file);
|
||||
source_file = 0;
|
||||
|
||||
fclose(defines_file);
|
||||
defines_file = 0;
|
||||
|
||||
if (source_count == 0) {
|
||||
fprintf(stderr, "%s: No input files.\n", argv[0]);
|
||||
fprintf(stderr, "%s\n", HELP);
|
||||
@@ -656,31 +659,16 @@ int main(int argc, char **argv)
|
||||
|
||||
/* Start building the preprocess command line. */
|
||||
|
||||
sprintf(tmp, "%s%civlpp %s%s -D__ICARUS__=1 -f%s ", pbase,sep,
|
||||
sprintf(tmp, "%s%civlpp %s%s -F%s -f%s ", pbase,sep,
|
||||
verbose_flag?" -v":"",
|
||||
e_flag?"":" -L", source_path);
|
||||
e_flag?"":" -L", defines_path, source_path);
|
||||
|
||||
ncmd = strlen(tmp);
|
||||
cmd = malloc(ncmd + 1);
|
||||
strcpy(cmd, tmp);
|
||||
|
||||
if (inc_list) {
|
||||
cmd = realloc(cmd, ncmd + strlen(inc_list) + 1);
|
||||
strcat(cmd, inc_list);
|
||||
ncmd += strlen(inc_list);
|
||||
}
|
||||
|
||||
if (def_list) {
|
||||
cmd = realloc(cmd, ncmd + strlen(def_list) + 1);
|
||||
strcat(cmd, def_list);
|
||||
ncmd += strlen(def_list);
|
||||
}
|
||||
|
||||
if (depfile) {
|
||||
cmd = realloc(cmd, ncmd + strlen(depfile) + 5);
|
||||
strcat(cmd, " -M ");
|
||||
strcat(cmd, depfile);
|
||||
ncmd += strlen(depfile) + 4;
|
||||
fprintf(defines_file, "M:%s\n", depfile);
|
||||
}
|
||||
|
||||
/* If the -E flag was given on the command line, then all we
|
||||
@@ -720,10 +708,8 @@ int main(int argc, char **argv)
|
||||
/* Write the preprocessor command needed to preprocess a
|
||||
single file. This may be used to preprocess library
|
||||
files. */
|
||||
fprintf(iconfig_file, "ivlpp:%s%civlpp -D__ICARUS__ -L %s %s\n",
|
||||
pbase, sep,
|
||||
inc_list? inc_list : "",
|
||||
def_list? def_list : "");
|
||||
fprintf(iconfig_file, "ivlpp:%s%civlpp -D__ICARUS__ -L -F%s\n",
|
||||
pbase, sep, defines_path);
|
||||
|
||||
/* Done writing to the iconfig file. Close it now. */
|
||||
fclose(iconfig_file);
|
||||
@@ -735,6 +721,12 @@ int main(int argc, char **argv)
|
||||
|
||||
/*
|
||||
* $Log: main.c,v $
|
||||
* Revision 1.69 2006/07/26 00:11:40 steve
|
||||
* Pass depfiles through temp defines file.
|
||||
*
|
||||
* Revision 1.68 2006/07/26 00:02:48 steve
|
||||
* Pass defines and includes through temp file.
|
||||
*
|
||||
* Revision 1.67 2005/07/14 23:38:44 steve
|
||||
* Display as version 0.9.devel
|
||||
*
|
||||
|
||||
+7
-1
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: elab_anet.cc,v 1.11 2005/07/11 16:56:50 steve Exp $"
|
||||
#ident "$Id: elab_anet.cc,v 1.12 2006/05/01 20:47:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -89,10 +89,13 @@ NetNet* PEConcat::elaborate_anet(Design*des, NetScope*scope) const
|
||||
|
||||
NetNet*osig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT_REG, pins);
|
||||
/* Assume that all the data types are the same. */
|
||||
osig->data_type(nets[0]->data_type());
|
||||
|
||||
pins = 0;
|
||||
for (unsigned idx = nets.count() ; idx > 0 ; idx -= 1) {
|
||||
NetNet*cur = nets[idx-1];
|
||||
assert(cur->data_type() == osig->data_type());
|
||||
for (unsigned pin = 0; pin < cur->pin_count(); pin += 1) {
|
||||
connect(osig->pin(pins), cur->pin(pin));
|
||||
pins += 1;
|
||||
@@ -166,6 +169,9 @@ NetNet* PEIdent::elaborate_anet(Design*des, NetScope*scope) const
|
||||
|
||||
/*
|
||||
* $Log: elab_anet.cc,v $
|
||||
* Revision 1.12 2006/05/01 20:47:58 steve
|
||||
* More explicit datatype setup.
|
||||
*
|
||||
* Revision 1.11 2005/07/11 16:56:50 steve
|
||||
* Remove NetVariable and ivl_variable_t structures.
|
||||
*
|
||||
|
||||
+117
-44
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: elab_expr.cc,v 1.102 2006/02/02 02:43:57 steve Exp $"
|
||||
#ident "$Id: elab_expr.cc,v 1.108 2006/08/09 05:19:08 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -28,7 +28,7 @@
|
||||
# include "netmisc.h"
|
||||
# include "util.h"
|
||||
|
||||
NetExpr* PExpr::elaborate_expr(Design*des, NetScope*, bool) const
|
||||
NetExpr* PExpr::elaborate_expr(Design*des, NetScope*, int, bool) const
|
||||
{
|
||||
cerr << get_line() << ": internal error: I do not know how to elaborate"
|
||||
<< " expression. " << endl;
|
||||
@@ -43,13 +43,14 @@ NetExpr* PExpr::elaborate_expr(Design*des, NetScope*, bool) const
|
||||
* and right sides, and creating one of a variety of different NetExpr
|
||||
* types.
|
||||
*/
|
||||
NetEBinary* PEBinary::elaborate_expr(Design*des, NetScope*scope, bool) const
|
||||
NetEBinary* PEBinary::elaborate_expr(Design*des, NetScope*scope,
|
||||
int expr_wid, bool) const
|
||||
{
|
||||
assert(left_);
|
||||
assert(right_);
|
||||
|
||||
NetExpr*lp = left_->elaborate_expr(des, scope);
|
||||
NetExpr*rp = right_->elaborate_expr(des, scope);
|
||||
NetExpr*lp = left_->elaborate_expr(des, scope, expr_wid, false);
|
||||
NetExpr*rp = right_->elaborate_expr(des, scope, expr_wid, false);
|
||||
if ((lp == 0) || (rp == 0)) {
|
||||
delete lp;
|
||||
delete rp;
|
||||
@@ -100,13 +101,29 @@ NetEBinary* PEBinary::elaborate_expr_base_(Design*des,
|
||||
tmp->set_line(*this);
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
tmp = new NetEBPow(op_, lp, rp);
|
||||
tmp->set_line(*this);
|
||||
break;
|
||||
|
||||
case '*':
|
||||
tmp = new NetEBMult(op_, lp, rp);
|
||||
tmp->set_line(*this);
|
||||
break;
|
||||
|
||||
case '/':
|
||||
case '%':
|
||||
/* The % operator does not support real arguments in
|
||||
baseline Verilog. But we allow it in our extended
|
||||
form of verilog. */
|
||||
if (generation_flag < GN_VER2001X) {
|
||||
if (lp->expr_type()==IVL_VT_REAL || rp->expr_type()==IVL_VT_REAL) {
|
||||
cerr << get_line() << ": error: Modulus operator may not "
|
||||
"have REAL operands." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
}
|
||||
/* Fall through to handle the % with the / operator. */
|
||||
case '/':
|
||||
tmp = new NetEBDiv(op_, lp, rp);
|
||||
tmp->set_line(*this);
|
||||
break;
|
||||
@@ -195,7 +212,7 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope) const
|
||||
}
|
||||
|
||||
PExpr*expr = parms_[0];
|
||||
NetExpr*sub = expr->elaborate_expr(des, scope, true);
|
||||
NetExpr*sub = expr->elaborate_expr(des, scope, -1, true);
|
||||
sub->cast_signed(true);
|
||||
return sub;
|
||||
}
|
||||
@@ -209,7 +226,7 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope) const
|
||||
}
|
||||
|
||||
PExpr*expr = parms_[0];
|
||||
NetExpr*sub = expr->elaborate_expr(des, scope, true);
|
||||
NetExpr*sub = expr->elaborate_expr(des, scope, -1, true);
|
||||
sub->cast_signed(false);
|
||||
return sub;
|
||||
}
|
||||
@@ -232,7 +249,7 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope) const
|
||||
<< " Use $bits() instead." << endl;
|
||||
|
||||
PExpr*expr = parms_[0];
|
||||
NetExpr*sub = expr->elaborate_expr(des, scope, true);
|
||||
NetExpr*sub = expr->elaborate_expr(des, scope, -1, true);
|
||||
verinum val (sub->expr_width(), 8*sizeof(unsigned));
|
||||
delete sub;
|
||||
|
||||
@@ -255,7 +272,7 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope) const
|
||||
}
|
||||
|
||||
PExpr*expr = parms_[0];
|
||||
NetExpr*sub = expr->elaborate_expr(des, scope, true);
|
||||
NetExpr*sub = expr->elaborate_expr(des, scope, -1, true);
|
||||
|
||||
verinum val (sub->has_sign()? verinum::V1 : verinum::V0, 1);
|
||||
delete sub;
|
||||
@@ -303,7 +320,7 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope) const
|
||||
for (unsigned idx = 0 ; idx < nparms ; idx += 1) {
|
||||
PExpr*expr = parms_[idx];
|
||||
if (expr) {
|
||||
NetExpr*tmp1 = expr->elaborate_expr(des, scope, true);
|
||||
NetExpr*tmp1 = expr->elaborate_expr(des, scope, -1, true);
|
||||
if (NetExpr*tmp2 = tmp1->eval_tree()) {
|
||||
delete tmp1;
|
||||
fun->parm(idx, tmp2);
|
||||
@@ -329,7 +346,8 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope) const
|
||||
return fun;
|
||||
}
|
||||
|
||||
NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope, bool) const
|
||||
NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
|
||||
int expr_wid, bool) const
|
||||
{
|
||||
if (path_.peek_name(0)[0] == '$')
|
||||
return elaborate_sfunc_(des, scope);
|
||||
@@ -366,7 +384,7 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope, bool) const
|
||||
for (unsigned idx = 0 ; idx < parms.count() ; idx += 1) {
|
||||
PExpr*tmp = parms_[idx];
|
||||
if (tmp) {
|
||||
parms[idx] = tmp->elaborate_expr(des, scope);
|
||||
parms[idx] = tmp->elaborate_expr(des, scope, -1, false);
|
||||
|
||||
} else {
|
||||
missing_parms += 1;
|
||||
@@ -405,14 +423,15 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope, bool) const
|
||||
}
|
||||
|
||||
|
||||
NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope, bool) const
|
||||
NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope,
|
||||
int expr_wid, bool) const
|
||||
{
|
||||
NetExpr* repeat = 0;
|
||||
|
||||
/* If there is a repeat expression, then evaluate the constant
|
||||
value and set the repeat count. */
|
||||
if (repeat_) {
|
||||
NetExpr*tmp = elab_and_eval(des, scope, repeat_);
|
||||
NetExpr*tmp = elab_and_eval(des, scope, repeat_, -1);
|
||||
assert(tmp);
|
||||
NetEConst*rep = dynamic_cast<NetEConst*>(tmp);
|
||||
|
||||
@@ -444,7 +463,7 @@ NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope, bool) const
|
||||
}
|
||||
|
||||
assert(parms_[idx]);
|
||||
NetExpr*ex = elab_and_eval(des, scope, parms_[idx]);
|
||||
NetExpr*ex = elab_and_eval(des, scope, parms_[idx], -1);
|
||||
if (ex == 0) continue;
|
||||
|
||||
ex->set_line(*parms_[idx]);
|
||||
@@ -465,7 +484,7 @@ NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope, bool) const
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetExpr* PEFNumber::elaborate_expr(Design*des, NetScope*scope, bool) const
|
||||
NetExpr* PEFNumber::elaborate_expr(Design*des, NetScope*scope, int, bool) const
|
||||
{
|
||||
NetECReal*tmp = new NetECReal(*value_);
|
||||
tmp->set_line(*this);
|
||||
@@ -484,7 +503,7 @@ NetExpr* PEFNumber::elaborate_expr(Design*des, NetScope*scope, bool) const
|
||||
* The signal name may be escaped, but that affects nothing here.
|
||||
*/
|
||||
NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
||||
bool sys_task_arg) const
|
||||
int expr_wid, bool sys_task_arg) const
|
||||
{
|
||||
assert(scope);
|
||||
|
||||
@@ -555,7 +574,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
||||
PExpr*addr = idx_[0];
|
||||
assert(addr);
|
||||
|
||||
NetExpr*i = addr->elaborate_expr(des, scope);
|
||||
NetExpr*i = addr->elaborate_expr(des, scope, -1, false);
|
||||
if (i == 0) {
|
||||
cerr << get_line() << ": error: Unable to elaborate "
|
||||
"index expression `" << *addr << "'" << endl;
|
||||
@@ -575,8 +594,8 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
||||
|
||||
if (sel_ == SEL_PART) {
|
||||
|
||||
NetExpr*le = elab_and_eval(des, scope, lsb_);
|
||||
NetExpr*me = elab_and_eval(des, scope, msb_);
|
||||
NetExpr*le = elab_and_eval(des, scope, lsb_, -1);
|
||||
NetExpr*me = elab_and_eval(des, scope, msb_, -1);
|
||||
|
||||
NetEConst*lec = dynamic_cast<NetEConst*>(le);
|
||||
NetEConst*mec = dynamic_cast<NetEConst*>(me);
|
||||
@@ -601,7 +620,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
||||
|
||||
assert(sel_ == SEL_IDX_UP || sel_ == SEL_IDX_DO);
|
||||
|
||||
NetExpr*wid_ex = elab_and_eval(des, scope, lsb_);
|
||||
NetExpr*wid_ex = elab_and_eval(des, scope, lsb_, -1);
|
||||
NetEConst*wid_ec = dynamic_cast<NetEConst*> (wid_ex);
|
||||
if (wid_ec == 0) {
|
||||
cerr << lsb_->get_line() << ": error: "
|
||||
@@ -613,7 +632,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
||||
|
||||
unsigned wid = wid_ec->value().as_ulong();
|
||||
|
||||
NetExpr*idx_ex = elab_and_eval(des, scope, msb_);
|
||||
NetExpr*idx_ex = elab_and_eval(des, scope, msb_, -1);
|
||||
if (idx_ex == 0) {
|
||||
return 0;
|
||||
}
|
||||
@@ -637,6 +656,18 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
||||
return tmp;
|
||||
}
|
||||
|
||||
// Hmm... maybe this is a genvar? This is only possible while
|
||||
// processing generate blocks, but then the genvar_tmp will be
|
||||
// set in the scope.
|
||||
if (path_.component_count() == 1
|
||||
&& scope->genvar_tmp.str()
|
||||
&& strcmp(path_.peek_name(0), scope->genvar_tmp) == 0) {
|
||||
verinum val (scope->genvar_tmp_val);
|
||||
NetEConst*tmp = new NetEConst(val);
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
// Finally, if this is a scope name, then return that. Look
|
||||
// first to see if this is a name of a local scope. Failing
|
||||
// that, search globally for a hierarchical name.
|
||||
@@ -759,7 +790,7 @@ NetExpr* PEIdent::elaborate_expr_param(Design*des,
|
||||
|
||||
/* Get and evaluate the width of the index
|
||||
select. This must be constant. */
|
||||
NetExpr*wid_ex = elab_and_eval(des, scope, lsb_);
|
||||
NetExpr*wid_ex = elab_and_eval(des, scope, lsb_, -1);
|
||||
NetEConst*wid_ec = dynamic_cast<NetEConst*> (wid_ex);
|
||||
if (wid_ec == 0) {
|
||||
cerr << lsb_->get_line() << ": error: "
|
||||
@@ -771,7 +802,7 @@ NetExpr* PEIdent::elaborate_expr_param(Design*des,
|
||||
|
||||
unsigned wid = wid_ec->value().as_ulong();
|
||||
|
||||
NetExpr*idx_ex = elab_and_eval(des, scope, msb_);
|
||||
NetExpr*idx_ex = elab_and_eval(des, scope, msb_, -1);
|
||||
if (idx_ex == 0) {
|
||||
return 0;
|
||||
}
|
||||
@@ -794,7 +825,7 @@ NetExpr* PEIdent::elaborate_expr_param(Design*des,
|
||||
/* Handle the case where a parameter has a bit
|
||||
select attached to it. Generate a NetESelect
|
||||
object to select the bit as desired. */
|
||||
NetExpr*mtmp = idx_[0]->elaborate_expr(des, scope);
|
||||
NetExpr*mtmp = idx_[0]->elaborate_expr(des, scope, -1,false);
|
||||
if (! dynamic_cast<NetEConst*>(mtmp)) {
|
||||
NetExpr*re = mtmp->eval_tree();
|
||||
if (re) {
|
||||
@@ -973,9 +1004,9 @@ NetExpr* PEIdent::elaborate_expr_net_idx_up_(Design*des, NetScope*scope,
|
||||
NetESignal*sig = new NetESignal(net);
|
||||
sig->set_line(*this);
|
||||
|
||||
NetExpr*base = elab_and_eval(des, scope, msb_);
|
||||
NetExpr*base = elab_and_eval(des, scope, msb_, -1);
|
||||
|
||||
NetExpr*wid_e = elab_and_eval(des, scope, lsb_);
|
||||
NetExpr*wid_e = elab_and_eval(des, scope, lsb_, -1);
|
||||
NetEConst*wid_c = dynamic_cast<NetEConst*> (wid_e);
|
||||
if (wid_c == 0) {
|
||||
cerr << get_line() << ": error: Width of indexed part select "
|
||||
@@ -1026,9 +1057,9 @@ NetExpr* PEIdent::elaborate_expr_net_idx_do_(Design*des, NetScope*scope,
|
||||
NetESignal*sig = new NetESignal(net);
|
||||
sig->set_line(*this);
|
||||
|
||||
NetExpr*base = elab_and_eval(des, scope, msb_);
|
||||
NetExpr*base = elab_and_eval(des, scope, msb_, -1);
|
||||
|
||||
NetExpr*wid_e = elab_and_eval(des, scope, lsb_);
|
||||
NetExpr*wid_e = elab_and_eval(des, scope, lsb_, -1);
|
||||
NetEConst*wid_c = dynamic_cast<NetEConst*> (wid_e);
|
||||
if (wid_c == 0) {
|
||||
cerr << get_line() << ": error: Width of indexed part select "
|
||||
@@ -1124,7 +1155,7 @@ 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.
|
||||
NetExpr*ex = idx_[0]->elaborate_expr(des, scope);
|
||||
NetExpr*ex = idx_[0]->elaborate_expr(des, scope, -1, false);
|
||||
|
||||
if (net->msb() < net->lsb()) {
|
||||
ex = make_sub_expr(net->lsb(), ex);
|
||||
@@ -1169,15 +1200,27 @@ NetExpr* PEIdent::elaborate_expr_net(Design*des, NetScope*scope,
|
||||
return node;
|
||||
}
|
||||
|
||||
NetEConst* PENumber::elaborate_expr(Design*des, NetScope*, bool) const
|
||||
NetEConst* PENumber::elaborate_expr(Design*des, NetScope*,
|
||||
int expr_width, bool) const
|
||||
{
|
||||
assert(value_);
|
||||
NetEConst*tmp = new NetEConst(*value_);
|
||||
verinum tvalue = *value_;
|
||||
|
||||
// If the expr_width is >0, then the context is requesting a
|
||||
// specific size (for example this is part of the r-values of
|
||||
// an assignment) so we pad to the desired width and ignore
|
||||
// the self-determined size.
|
||||
if (expr_width > 0) {
|
||||
tvalue = pad_to_width(tvalue, expr_width);
|
||||
}
|
||||
|
||||
NetEConst*tmp = new NetEConst(tvalue);
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetEConst* PEString::elaborate_expr(Design*des, NetScope*, bool) const
|
||||
NetEConst* PEString::elaborate_expr(Design*des, NetScope*,
|
||||
int expr_width, bool) const
|
||||
{
|
||||
NetEConst*tmp = new NetEConst(value());
|
||||
tmp->set_line(*this);
|
||||
@@ -1202,23 +1245,24 @@ static bool test_ternary_operand_compat(ivl_variable_type_t l,
|
||||
* parsed so I can presume that they exist, and call elaboration
|
||||
* methods. If any elaboration fails, then give up and return 0.
|
||||
*/
|
||||
NetETernary*PETernary::elaborate_expr(Design*des, NetScope*scope, bool) const
|
||||
NetETernary*PETernary::elaborate_expr(Design*des, NetScope*scope,
|
||||
int expr_wid, bool) const
|
||||
{
|
||||
assert(expr_);
|
||||
assert(tru_);
|
||||
assert(fal_);
|
||||
|
||||
NetExpr*con = expr_->elaborate_expr(des, scope);
|
||||
NetExpr*con = expr_->elaborate_expr(des, scope, -1, false);
|
||||
if (con == 0)
|
||||
return 0;
|
||||
|
||||
NetExpr*tru = tru_->elaborate_expr(des, scope);
|
||||
NetExpr*tru = tru_->elaborate_expr(des, scope, expr_wid, false);
|
||||
if (tru == 0) {
|
||||
delete con;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetExpr*fal = fal_->elaborate_expr(des, scope);
|
||||
NetExpr*fal = fal_->elaborate_expr(des, scope, expr_wid, false);
|
||||
if (fal == 0) {
|
||||
delete con;
|
||||
delete tru;
|
||||
@@ -1239,9 +1283,10 @@ NetETernary*PETernary::elaborate_expr(Design*des, NetScope*scope, bool) const
|
||||
return res;
|
||||
}
|
||||
|
||||
NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope, bool) const
|
||||
NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope,
|
||||
int expr_wid, bool) const
|
||||
{
|
||||
NetExpr*ip = expr_->elaborate_expr(des, scope);
|
||||
NetExpr*ip = expr_->elaborate_expr(des, scope, expr_wid, false);
|
||||
if (ip == 0) return 0;
|
||||
|
||||
/* Should we evaluate expressions ahead of time,
|
||||
@@ -1257,14 +1302,22 @@ NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope, bool) const
|
||||
|
||||
case '-':
|
||||
if (NetEConst*ipc = dynamic_cast<NetEConst*>(ip)) {
|
||||
|
||||
verinum val = ipc->value();
|
||||
if (expr_wid > 0)
|
||||
val = pad_to_width(val, expr_wid);
|
||||
|
||||
/* When taking the - of a number, turn it into a
|
||||
signed expression and extend it one bit to
|
||||
accommodate a possible sign bit. */
|
||||
verinum val = ipc->value();
|
||||
verinum zero (verinum::V0, val.len()+1, val.has_len());
|
||||
val = zero - val;
|
||||
val.has_sign(true);
|
||||
tmp = new NetEConst(val);
|
||||
verinum nval = zero - val;
|
||||
|
||||
if (val.has_len())
|
||||
nval = verinum(nval, val.len());
|
||||
nval.has_sign(true);
|
||||
tmp = new NetEConst(nval);
|
||||
tmp->set_line(*this);
|
||||
delete ip;
|
||||
|
||||
} else if (NetECReal*ipc = dynamic_cast<NetECReal*>(ip)) {
|
||||
@@ -1345,6 +1398,26 @@ NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope, bool) const
|
||||
|
||||
/*
|
||||
* $Log: elab_expr.cc,v $
|
||||
* Revision 1.108 2006/08/09 05:19:08 steve
|
||||
* Add support for real valued modulus.
|
||||
*
|
||||
* Revision 1.107 2006/07/31 03:50:17 steve
|
||||
* Add support for power in constant expressions.
|
||||
*
|
||||
* Revision 1.106 2006/07/07 04:06:37 steve
|
||||
* Fix context determined with of constants.
|
||||
*
|
||||
* Revision 1.105 2006/06/02 04:48:49 steve
|
||||
* Make elaborate_expr methods aware of the width that the context
|
||||
* requires of it. In the process, fix sizing of the width of unary
|
||||
* minus is context determined sizes.
|
||||
*
|
||||
* Revision 1.104 2006/06/01 03:54:51 steve
|
||||
* Fix broken subtraction of small constants.
|
||||
*
|
||||
* Revision 1.103 2006/04/12 05:05:03 steve
|
||||
* Use elab_and_eval to evaluate genvar expressions.
|
||||
*
|
||||
* Revision 1.102 2006/02/02 02:43:57 steve
|
||||
* Allow part selects of memory words in l-values.
|
||||
*
|
||||
|
||||
+182
-46
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: elab_lval.cc,v 1.33 2006/02/02 02:43:57 steve Exp $"
|
||||
#ident "$Id: elab_lval.cc,v 1.36 2006/06/02 04:48:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -179,6 +179,15 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
||||
|
||||
assert(reg);
|
||||
|
||||
if (sel_ == SEL_PART)
|
||||
return elaborate_lval_net_part_(des, scope, reg);
|
||||
|
||||
if (sel_ == SEL_IDX_UP)
|
||||
return elaborate_lval_net_idx_up_(des, scope, reg);
|
||||
|
||||
if (sel_ == SEL_IDX_DO)
|
||||
return elaborate_lval_net_idx_do_(des, scope, reg);
|
||||
|
||||
/* Get the signal referenced by the identifier, and make sure
|
||||
it is a register. Wires are not allows in this context,
|
||||
unless this is the l-value of a force. */
|
||||
@@ -192,54 +201,22 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(msb_ == 0);
|
||||
assert(lsb_ == 0);
|
||||
long msb, lsb;
|
||||
NetExpr*mux;
|
||||
|
||||
if (msb_ || lsb_) {
|
||||
assert(msb_ && lsb_);
|
||||
|
||||
/* This handles part selects. In this case, there are
|
||||
two bit select expressions, and both must be
|
||||
constant. Evaluate them and pass the results back to
|
||||
the caller. */
|
||||
verinum*vl = lsb_->eval_const(des, scope);
|
||||
if (vl == 0) {
|
||||
cerr << lsb_->get_line() << ": error: "
|
||||
"Part select expressions must be constant."
|
||||
<< endl;
|
||||
cerr << lsb_->get_line() << ": : This lsb expression "
|
||||
"violates the rule: " << *lsb_ << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
verinum*vm = msb_->eval_const(des, scope);
|
||||
if (vm == 0) {
|
||||
cerr << msb_->get_line() << ": error: "
|
||||
"Part select expressions must be constant."
|
||||
<< endl;
|
||||
cerr << msb_->get_line() << ": : This msb expression "
|
||||
"violates the rule: " << *msb_ << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
msb = vm->as_long();
|
||||
lsb = vl->as_long();
|
||||
mux = 0;
|
||||
|
||||
} else if (! idx_.empty()) {
|
||||
if (! idx_.empty()) {
|
||||
|
||||
/* If there is only a single select expression, it is a
|
||||
bit select. Evaluate the constant value and treat it
|
||||
as a part select with a bit width of 1. If the
|
||||
expression it not constant, then return the
|
||||
expression as a mux. */
|
||||
assert(msb_ == 0);
|
||||
assert(lsb_ == 0);
|
||||
assert(idx_.size() == 1);
|
||||
verinum*v = idx_[0]->eval_const(des, scope);
|
||||
if (v == 0) {
|
||||
NetExpr*m = idx_[0]->elaborate_expr(des, scope);
|
||||
NetExpr*m = idx_[0]->elaborate_expr(des, scope, -1, false);
|
||||
assert(m);
|
||||
msb = 0;
|
||||
lsb = 0;
|
||||
@@ -257,8 +234,6 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
||||
/* No select expressions, so presume a part select the
|
||||
width of the register. */
|
||||
|
||||
assert(msb_ == 0);
|
||||
assert(lsb_ == 0);
|
||||
msb = reg->msb();
|
||||
lsb = reg->lsb();
|
||||
mux = 0;
|
||||
@@ -273,7 +248,13 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
||||
bmux to select the target bit. */
|
||||
lv = new NetAssign_(reg);
|
||||
|
||||
lv->set_bmux(mux);
|
||||
/* Correct the mux for the range of the vector. */
|
||||
if (reg->msb() < reg->lsb())
|
||||
mux = make_sub_expr(reg->lsb(), mux);
|
||||
else if (reg->lsb() != 0)
|
||||
mux = make_add_expr(mux, - reg->lsb());
|
||||
|
||||
lv->set_part(mux, 1);
|
||||
|
||||
} else if (msb == reg->msb() && lsb == reg->lsb()) {
|
||||
|
||||
@@ -319,6 +300,150 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
||||
return lv;
|
||||
}
|
||||
|
||||
NetAssign_* PEIdent::elaborate_lval_net_part_(Design*des,
|
||||
NetScope*scope,
|
||||
NetNet*reg) const
|
||||
{
|
||||
assert(msb_ && lsb_);
|
||||
|
||||
/* This handles part selects. In this case, there are
|
||||
two bit select expressions, and both must be
|
||||
constant. Evaluate them and pass the results back to
|
||||
the caller. */
|
||||
NetExpr*lsb_ex = elab_and_eval(des, scope, lsb_, -1);
|
||||
NetEConst*lsb_c = dynamic_cast<NetEConst*>(lsb_ex);
|
||||
if (lsb_c == 0) {
|
||||
cerr << lsb_->get_line() << ": error: "
|
||||
"Part select expressions must be constant."
|
||||
<< endl;
|
||||
cerr << lsb_->get_line() << ": : This lsb expression "
|
||||
"violates the rule: " << *lsb_ << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetExpr*msb_ex = elab_and_eval(des, scope, msb_, -1);
|
||||
NetEConst*msb_c = dynamic_cast<NetEConst*>(msb_ex);
|
||||
if (msb_c == 0) {
|
||||
cerr << msb_->get_line() << ": error: "
|
||||
"Part select expressions must be constant."
|
||||
<< endl;
|
||||
cerr << msb_->get_line() << ": : This msb expression "
|
||||
"violates the rule: " << *msb_ << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
long msb = msb_c->value().as_long();
|
||||
long lsb = lsb_c->value().as_long();
|
||||
|
||||
delete msb_ex;
|
||||
delete lsb_ex;
|
||||
|
||||
NetAssign_*lv = 0;
|
||||
|
||||
if (msb == reg->msb() && lsb == reg->lsb()) {
|
||||
|
||||
/* No bit select, and part select covers the entire
|
||||
vector. Simplest case. */
|
||||
lv = new NetAssign_(reg);
|
||||
|
||||
} else {
|
||||
|
||||
/* If the bit/part select is constant, then make the
|
||||
NetAssign_ only as wide as it needs to be and connect
|
||||
only to the selected bits of the reg. */
|
||||
unsigned loff = reg->sb_to_idx(lsb);
|
||||
unsigned moff = reg->sb_to_idx(msb);
|
||||
unsigned wid = moff - loff + 1;
|
||||
|
||||
if (moff < loff) {
|
||||
cerr << get_line() << ": error: part select "
|
||||
<< reg->name() << "[" << msb<<":"<<lsb<<"]"
|
||||
<< " is reversed." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If the part select extends beyond the extreme of the
|
||||
variable, then report an error. Note that loff is
|
||||
converted to normalized form so is relative the
|
||||
variable pins. */
|
||||
|
||||
if ((wid + loff) > reg->vector_width()) {
|
||||
cerr << get_line() << ": error: bit/part select "
|
||||
<< reg->name() << "[" << msb<<":"<<lsb<<"]"
|
||||
<< " is out of range." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
lv = new NetAssign_(reg);
|
||||
lv->set_part(new NetEConst(verinum(loff)), wid);
|
||||
}
|
||||
|
||||
return lv;
|
||||
}
|
||||
|
||||
NetAssign_* PEIdent::elaborate_lval_net_idx_up_(Design*des,
|
||||
NetScope*scope,
|
||||
NetNet*reg) const
|
||||
{
|
||||
assert(lsb_);
|
||||
assert(msb_);
|
||||
|
||||
if (reg->type() != NetNet::REG) {
|
||||
cerr << get_line() << ": error: " << path_ <<
|
||||
" is not a reg/integer/time in " << scope->name() <<
|
||||
"." << endl;
|
||||
cerr << reg->get_line() << ": : " << path_ <<
|
||||
" is declared here as " << reg->type() << "." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Calculate the width expression (in the lsb_ position)
|
||||
first. If the expression is not constant, error but guess 1
|
||||
so we can keep going and find more errors. */
|
||||
NetExpr*wid_ex = elab_and_eval(des, scope, lsb_, -1);
|
||||
NetEConst*wid_c = dynamic_cast<NetEConst*>(wid_ex);
|
||||
|
||||
if (wid_c == 0) {
|
||||
cerr << get_line() << ": error: Indexed part width must be "
|
||||
<< "constant. Expression in question is..." << endl;
|
||||
cerr << get_line() << ": : " << *wid_ex << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
unsigned wid = wid_c? wid_c->value().as_ulong() : 1;
|
||||
delete wid_ex;
|
||||
|
||||
NetExpr*base = elab_and_eval(des, scope, msb_, -1);
|
||||
|
||||
/* Correct the mux for the range of the vector. */
|
||||
if (reg->msb() < reg->lsb())
|
||||
base = make_sub_expr(reg->lsb(), base);
|
||||
else if (reg->lsb() != 0)
|
||||
base = make_add_expr(base, - reg->lsb());
|
||||
|
||||
NetAssign_*lv = new NetAssign_(reg);
|
||||
lv->set_part(base, wid);
|
||||
|
||||
return lv;
|
||||
}
|
||||
|
||||
NetAssign_* PEIdent::elaborate_lval_net_idx_do_(Design*des,
|
||||
NetScope*scope,
|
||||
NetNet*reg) const
|
||||
{
|
||||
assert(lsb_);
|
||||
assert(msb_);
|
||||
cerr << get_line() << ": internal error: don't know how to "
|
||||
"deal with SEL_IDX_DO in lval?" << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetAssign_* PEIdent::elaborate_mem_lval_(Design*des, NetScope*scope,
|
||||
NetMemory*mem) const
|
||||
{
|
||||
@@ -343,7 +468,7 @@ NetAssign_* PEIdent::elaborate_mem_lval_(Design*des, NetScope*scope,
|
||||
assert(idx_.size() == 1);
|
||||
|
||||
/* Elaborate the address expression. */
|
||||
NetExpr*ix = elab_and_eval(des, scope, idx_[0]);
|
||||
NetExpr*ix = elab_and_eval(des, scope, idx_[0], -1);
|
||||
if (ix == 0)
|
||||
return 0;
|
||||
|
||||
@@ -352,7 +477,7 @@ NetAssign_* PEIdent::elaborate_mem_lval_(Design*des, NetScope*scope,
|
||||
|
||||
/* If there is no extra part select, then we are done. */
|
||||
if (msb_ == 0 && lsb_ == 0) {
|
||||
lv->set_part(0U, mem->width());
|
||||
lv->set_part(0, mem->width());
|
||||
return lv;
|
||||
}
|
||||
|
||||
@@ -360,8 +485,8 @@ NetAssign_* PEIdent::elaborate_mem_lval_(Design*des, NetScope*scope,
|
||||
assert(msb_ && lsb_);
|
||||
|
||||
if (sel_ == SEL_PART) {
|
||||
NetExpr*le = elab_and_eval(des, scope, lsb_);
|
||||
NetExpr*me = elab_and_eval(des, scope, msb_);
|
||||
NetExpr*le = elab_and_eval(des, scope, lsb_, -1);
|
||||
NetExpr*me = elab_and_eval(des, scope, msb_, -1);
|
||||
|
||||
NetEConst*lec = dynamic_cast<NetEConst*>(le);
|
||||
NetEConst*mec = dynamic_cast<NetEConst*>(me);
|
||||
@@ -384,7 +509,7 @@ NetAssign_* PEIdent::elaborate_mem_lval_(Design*des, NetScope*scope,
|
||||
|
||||
assert(sel_ == SEL_IDX_UP || sel_ == SEL_IDX_DO);
|
||||
|
||||
NetExpr*wid_ex = elab_and_eval(des, scope, lsb_);
|
||||
NetExpr*wid_ex = elab_and_eval(des, scope, lsb_, -1);
|
||||
NetEConst*wid_ec = dynamic_cast<NetEConst*> (wid_ex);
|
||||
if (wid_ec == 0) {
|
||||
cerr << lsb_->get_line() << ": error: "
|
||||
@@ -396,7 +521,7 @@ NetAssign_* PEIdent::elaborate_mem_lval_(Design*des, NetScope*scope,
|
||||
|
||||
unsigned wid = wid_ec->value().as_ulong();
|
||||
|
||||
NetExpr*base_ex = elab_and_eval(des, scope, msb_);
|
||||
NetExpr*base_ex = elab_and_eval(des, scope, msb_, -1);
|
||||
if (base_ex == 0) {
|
||||
return 0;
|
||||
}
|
||||
@@ -419,6 +544,17 @@ NetAssign_* PENumber::elaborate_lval(Design*des, NetScope*, bool) const
|
||||
|
||||
/*
|
||||
* $Log: elab_lval.cc,v $
|
||||
* Revision 1.36 2006/06/02 04:48:50 steve
|
||||
* Make elaborate_expr methods aware of the width that the context
|
||||
* requires of it. In the process, fix sizing of the width of unary
|
||||
* minus is context determined sizes.
|
||||
*
|
||||
* Revision 1.35 2006/04/16 00:54:04 steve
|
||||
* Cleanup lval part select handling.
|
||||
*
|
||||
* Revision 1.34 2006/04/16 00:15:43 steve
|
||||
* Fix part selects in l-values.
|
||||
*
|
||||
* Revision 1.33 2006/02/02 02:43:57 steve
|
||||
* Allow part selects of memory words in l-values.
|
||||
*
|
||||
|
||||
+319
-109
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: elab_net.cc,v 1.179 2006/04/10 00:32:14 steve Exp $"
|
||||
#ident "$Id: elab_net.cc,v 1.189 2006/08/08 05:11:37 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -209,14 +209,21 @@ NetNet* PEBinary::elaborate_net_add_(Design*des, NetScope*scope,
|
||||
assert(0);
|
||||
}
|
||||
|
||||
bool expr_signed = lsig->get_signed() && rsig->get_signed();
|
||||
|
||||
// Pad out the operands, if necessary, the match the width of
|
||||
// the adder device.
|
||||
if (lsig->vector_width() < width)
|
||||
lsig = pad_to_width(des, lsig, width);
|
||||
if (expr_signed)
|
||||
lsig = pad_to_width_signed(des, lsig, width);
|
||||
else
|
||||
lsig = pad_to_width(des, lsig, width);
|
||||
|
||||
if (rsig->vector_width() < width)
|
||||
rsig = pad_to_width(des, rsig, width);
|
||||
if (expr_signed)
|
||||
rsig = pad_to_width_signed(des, rsig, width);
|
||||
else
|
||||
rsig = pad_to_width(des, rsig, width);
|
||||
|
||||
// Check that the argument types match.
|
||||
if (lsig->data_type() != rsig->data_type()) {
|
||||
@@ -232,6 +239,7 @@ NetNet* PEBinary::elaborate_net_add_(Design*des, NetScope*scope,
|
||||
osig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, owidth);
|
||||
osig->data_type(lsig->data_type());
|
||||
osig->set_signed(expr_signed);
|
||||
osig->local_flag(true);
|
||||
if (debug_elaborate) {
|
||||
cerr << get_line() << ": debug: Elaborate NetAddSub "
|
||||
@@ -383,6 +391,7 @@ static NetNet* compare_eq_constant(Design*des, NetScope*scope,
|
||||
1);
|
||||
NetEConst*ogate = new NetEConst(oval);
|
||||
NetNet*osig = ogate->synthesize(des);
|
||||
osig->data_type(lsig->data_type());
|
||||
delete ogate;
|
||||
|
||||
if (debug_elaborate)
|
||||
@@ -437,7 +446,7 @@ static NetNet* compare_eq_constant(Design*des, NetScope*scope,
|
||||
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, 0, 0);
|
||||
tmp->data_type(IVL_VT_LOGIC);
|
||||
tmp->data_type(lsig->data_type());
|
||||
tmp->local_flag(true);
|
||||
tmp->set_line(*lsig);
|
||||
|
||||
@@ -473,7 +482,7 @@ NetNet* PEBinary::elaborate_net_cmp_(Design*des, NetScope*scope,
|
||||
(so that the eval_tree method can reduce constant
|
||||
expressions, including parameters) then turn those results
|
||||
into synthesized nets. */
|
||||
NetExpr*lexp = elab_and_eval(des, scope, left_);
|
||||
NetExpr*lexp = elab_and_eval(des, scope, left_, lwidth);
|
||||
if (lexp == 0) {
|
||||
cerr << get_line() << ": error: Cannot elaborate ";
|
||||
left_->dump(cerr);
|
||||
@@ -481,7 +490,7 @@ NetNet* PEBinary::elaborate_net_cmp_(Design*des, NetScope*scope,
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetExpr*rexp = elab_and_eval(des, scope, right_);
|
||||
NetExpr*rexp = elab_and_eval(des, scope, right_, lwidth);
|
||||
if (rexp == 0) {
|
||||
cerr << get_line() << ": error: Cannot elaborate ";
|
||||
right_->dump(cerr);
|
||||
@@ -872,6 +881,7 @@ NetNet* PEBinary::elaborate_net_log_(Design*des, NetScope*scope,
|
||||
temporary signal to represent it. */
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, 1);
|
||||
tmp->data_type(IVL_VT_LOGIC);
|
||||
tmp->local_flag(true);
|
||||
connect(gate->pin(1), tmp->pin(0));
|
||||
|
||||
@@ -893,6 +903,7 @@ NetNet* PEBinary::elaborate_net_log_(Design*des, NetScope*scope,
|
||||
temporary signal to represent it. */
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, 1);
|
||||
tmp->data_type(IVL_VT_LOGIC);
|
||||
tmp->local_flag(true);
|
||||
connect(gate->pin(2), tmp->pin(0));
|
||||
|
||||
@@ -942,6 +953,7 @@ NetNet* PEBinary::elaborate_net_mul_(Design*des, NetScope*scope,
|
||||
connect(odev->pin(idx), osig->pin(idx));
|
||||
|
||||
des->add_node(odev);
|
||||
osig->data_type(IVL_VT_LOGIC);
|
||||
osig->local_flag(true);
|
||||
return osig;
|
||||
}
|
||||
@@ -1205,39 +1217,11 @@ NetNet* PECallFunction::elaborate_net(Design*des, NetScope*scope,
|
||||
unsigned errors = 0;
|
||||
unsigned func_pins = 0;
|
||||
|
||||
/* Handle the special case that the function call is to
|
||||
$signed. This takes a single expression argument, and
|
||||
forces it to be a signed result. Otherwise, it is as if the
|
||||
$signed did not exist. */
|
||||
if (strcmp(path_.peek_name(0), "$signed") == 0) {
|
||||
if ((parms_.count() != 1) || (parms_[0] == 0)) {
|
||||
cerr << get_line() << ": error: The $signed() function "
|
||||
<< "takes exactly one(1) argument." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
if (path_.peek_name(0)[0] == '$')
|
||||
return elaborate_net_sfunc_(des, scope,
|
||||
width, rise, fall, decay,
|
||||
drive0, drive1);
|
||||
|
||||
PExpr*expr = parms_[0];
|
||||
NetNet*sub = expr->elaborate_net(des, scope, width, rise,
|
||||
fall, decay, drive0, drive1);
|
||||
sub->set_signed(true);
|
||||
return sub;
|
||||
}
|
||||
/* handle $unsigned like $signed */
|
||||
if (strcmp(path_.peek_name(0), "$unsigned") == 0) {
|
||||
if ((parms_.count() != 1) || (parms_[0] == 0)) {
|
||||
cerr << get_line() << ": error: The $unsigned() function "
|
||||
<< "takes exactly one(1) argument." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
PExpr*expr = parms_[0];
|
||||
NetNet*sub = expr->elaborate_net(des, scope, width, rise,
|
||||
fall, decay, drive0, drive1);
|
||||
sub->set_signed(false);
|
||||
return sub;
|
||||
}
|
||||
|
||||
/* Look up the function definition. */
|
||||
NetFuncDef*def = des->find_function(scope, path_);
|
||||
@@ -1298,6 +1282,7 @@ NetNet* PECallFunction::elaborate_net(Design*des, NetScope*scope,
|
||||
NetNet::WIRE,
|
||||
def->return_sig()->vector_width());
|
||||
osig->local_flag(true);
|
||||
osig->data_type(def->return_sig()->data_type());
|
||||
|
||||
connect(net->pin(0), osig->pin(0));
|
||||
|
||||
@@ -1314,6 +1299,87 @@ NetNet* PECallFunction::elaborate_net(Design*des, NetScope*scope,
|
||||
return osig;
|
||||
}
|
||||
|
||||
NetNet* PECallFunction::elaborate_net_sfunc_(Design*des, NetScope*scope,
|
||||
unsigned width,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const
|
||||
{
|
||||
/* Handle the special case that the function call is to
|
||||
$signed. This takes a single expression argument, and
|
||||
forces it to be a signed result. Otherwise, it is as if the
|
||||
$signed did not exist. */
|
||||
if (strcmp(path_.peek_name(0), "$signed") == 0) {
|
||||
if ((parms_.count() != 1) || (parms_[0] == 0)) {
|
||||
cerr << get_line() << ": error: The $signed() function "
|
||||
<< "takes exactly one(1) argument." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
PExpr*expr = parms_[0];
|
||||
NetNet*sub = expr->elaborate_net(des, scope, width, rise,
|
||||
fall, decay, drive0, drive1);
|
||||
sub->set_signed(true);
|
||||
return sub;
|
||||
}
|
||||
|
||||
/* handle $unsigned like $signed */
|
||||
if (strcmp(path_.peek_name(0), "$unsigned") == 0) {
|
||||
if ((parms_.count() != 1) || (parms_[0] == 0)) {
|
||||
cerr << get_line() << ": error: The $unsigned() function "
|
||||
<< "takes exactly one(1) argument." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
PExpr*expr = parms_[0];
|
||||
NetNet*sub = expr->elaborate_net(des, scope, width, rise,
|
||||
fall, decay, drive0, drive1);
|
||||
sub->set_signed(false);
|
||||
return sub;
|
||||
}
|
||||
|
||||
const struct sfunc_return_type*def = lookup_sys_func(path_.peek_name(0));
|
||||
|
||||
if (def == 0) {
|
||||
cerr << get_line() << ": error: System function "
|
||||
<< path_.peek_name(0) << " not defined." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetSysFunc*net = new NetSysFunc(scope, scope->local_symbol(),
|
||||
def, 1+parms_.count());
|
||||
des->add_node(net);
|
||||
net->set_line(*this);
|
||||
|
||||
NetNet*osig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, def->wid);
|
||||
osig->local_flag(true);
|
||||
osig->data_type(def->type);
|
||||
osig->set_line(*this);
|
||||
|
||||
connect(net->pin(0), osig->pin(0));
|
||||
|
||||
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
|
||||
NetNet*tmp = parms_[idx]->elaborate_net(des, scope, 0,
|
||||
0, 0, 0,
|
||||
Link::STRONG, Link::STRONG);
|
||||
if (tmp == 0) {
|
||||
cerr << get_line() << ": error: Unable to elaborate "
|
||||
<< "port " << idx << " of call to " << path_ <<
|
||||
"." << endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
connect(net->pin(1+idx), tmp->pin(0));
|
||||
}
|
||||
return osig;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The concatenation operator, as a net, is a wide signal that is
|
||||
@@ -1336,7 +1402,7 @@ NetNet* PEConcat::elaborate_net(Design*des, NetScope*scope,
|
||||
constant. This is used to generate the width of the
|
||||
concatenation. */
|
||||
if (repeat_) {
|
||||
NetExpr*etmp = elab_and_eval(des, scope, repeat_);
|
||||
NetExpr*etmp = elab_and_eval(des, scope, repeat_, -1);
|
||||
assert(etmp);
|
||||
NetEConst*erep = dynamic_cast<NetEConst*>(etmp);
|
||||
|
||||
@@ -1474,7 +1540,7 @@ NetNet* PEIdent::elaborate_net_bitmux_(Design*des, NetScope*scope,
|
||||
NetNet*sel;
|
||||
|
||||
if (sig->msb() < sig->lsb()) {
|
||||
NetExpr*sel_expr = idx_[0]->elaborate_expr(des, scope);
|
||||
NetExpr*sel_expr = idx_[0]->elaborate_expr(des, scope, -1, false);
|
||||
sel_expr = make_sub_expr(sig->lsb(), sel_expr);
|
||||
if (NetExpr*tmp = sel_expr->eval_tree()) {
|
||||
delete sel_expr;
|
||||
@@ -1484,7 +1550,7 @@ NetNet* PEIdent::elaborate_net_bitmux_(Design*des, NetScope*scope,
|
||||
sel = sel_expr->synthesize(des);
|
||||
|
||||
} else if (sig->lsb() != 0) {
|
||||
NetExpr*sel_expr = idx_[0]->elaborate_expr(des, scope);
|
||||
NetExpr*sel_expr = idx_[0]->elaborate_expr(des, scope, -1,false);
|
||||
sel_expr = make_add_expr(sel_expr, - sig->lsb());
|
||||
if (NetExpr*tmp = sel_expr->eval_tree()) {
|
||||
delete sel_expr;
|
||||
@@ -1553,7 +1619,7 @@ NetNet* PEIdent::elaborate_net(Design*des, NetScope*scope,
|
||||
constant value, extend the value to fit the desired
|
||||
output. */
|
||||
if (lwidth > pvalue.len()) {
|
||||
verinum tmp (0UL, lwidth);
|
||||
verinum tmp ((uint64_t)0, lwidth);
|
||||
for (unsigned idx = 0 ; idx < pvalue.len() ; idx += 1)
|
||||
tmp.set(idx, pvalue.get(idx));
|
||||
|
||||
@@ -1691,7 +1757,7 @@ NetNet* PEIdent::elaborate_net_ram_(Design*des, NetScope*scope,
|
||||
const bool must_be_self_determined_save = must_be_self_determined_flag;
|
||||
must_be_self_determined_flag = false;
|
||||
|
||||
NetExpr*adr_expr = elab_and_eval(des, scope, idx_[0]);
|
||||
NetExpr*adr_expr = elab_and_eval(des, scope, idx_[0], -1);
|
||||
|
||||
/* If an offset is needed, subtract it from the address to get
|
||||
an expression for the canonical address. */
|
||||
@@ -1733,8 +1799,9 @@ NetNet* PEIdent::elaborate_net_ram_(Design*des, NetScope*scope,
|
||||
* destination. The caller can connect gate outputs to this signal to
|
||||
* make the l-value connections.
|
||||
*/
|
||||
NetNet* PEConcat::elaborate_lnet(Design*des, NetScope*scope,
|
||||
bool implicit_net_ok) const
|
||||
NetNet* PEConcat::elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||
bool implicit_net_ok,
|
||||
bool bidirectional_flag) const
|
||||
{
|
||||
assert(scope);
|
||||
|
||||
@@ -1764,8 +1831,12 @@ NetNet* PEConcat::elaborate_lnet(Design*des, NetScope*scope,
|
||||
continue;
|
||||
}
|
||||
|
||||
nets[idx] = parms_[idx]->elaborate_lnet(des, scope,
|
||||
implicit_net_ok);
|
||||
if (bidirectional_flag) {
|
||||
nets[idx] = parms_[idx]->elaborate_bi_net(des, scope);
|
||||
} else {
|
||||
nets[idx] = parms_[idx]->elaborate_lnet(des, scope,
|
||||
implicit_net_ok);
|
||||
}
|
||||
if (nets[idx] == 0)
|
||||
errors += 1;
|
||||
else
|
||||
@@ -1790,6 +1861,9 @@ NetNet* PEConcat::elaborate_lnet(Design*des, NetScope*scope,
|
||||
NetNet*osig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, width);
|
||||
|
||||
/* Assume that the data types of the nets are all the same, so
|
||||
we can take the data type of any, the first will do. */
|
||||
osig->data_type(nets[0]->data_type());
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_line() << ": debug: Generating part selects "
|
||||
@@ -1797,11 +1871,14 @@ NetNet* PEConcat::elaborate_lnet(Design*des, NetScope*scope,
|
||||
<< endl;
|
||||
}
|
||||
|
||||
NetPartSelect::dir_t part_dir = bidirectional_flag
|
||||
? NetPartSelect::BI
|
||||
: NetPartSelect::VP;
|
||||
|
||||
for (unsigned idx = 0 ; idx < nets.count() ; idx += 1) {
|
||||
unsigned wid = nets[idx]->vector_width();
|
||||
unsigned off = width - wid;
|
||||
NetPartSelect*ps = new NetPartSelect(osig, off, wid,
|
||||
NetPartSelect::VP);
|
||||
NetPartSelect*ps = new NetPartSelect(osig, off, wid, part_dir);
|
||||
des->add_node(ps);
|
||||
|
||||
connect(ps->pin(1), osig->pin(0));
|
||||
@@ -1812,10 +1889,22 @@ NetNet* PEConcat::elaborate_lnet(Design*des, NetScope*scope,
|
||||
}
|
||||
assert(width == 0);
|
||||
|
||||
osig->data_type(nets[0]->data_type());
|
||||
osig->local_flag(true);
|
||||
return osig;
|
||||
}
|
||||
|
||||
NetNet* PEConcat::elaborate_lnet(Design*des, NetScope*scope,
|
||||
bool implicit_net_ok) const
|
||||
{
|
||||
return elaborate_lnet_common_(des, scope, implicit_net_ok, false);
|
||||
}
|
||||
|
||||
NetNet* PEConcat::elaborate_bi_net(Design*des, NetScope*scope) const
|
||||
{
|
||||
return elaborate_lnet_common_(des, scope, true, true);
|
||||
}
|
||||
|
||||
/*
|
||||
* Elaborate a number as a NetConst object.
|
||||
*/
|
||||
@@ -1884,69 +1973,138 @@ NetNet* PEIdent::make_implicit_net_(Design*des, NetScope*scope) const
|
||||
bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
|
||||
unsigned&midx, unsigned&lidx) const
|
||||
{
|
||||
if (msb_ && lsb_) {
|
||||
verinum*mval = msb_->eval_const(des, scope);
|
||||
assert(mval);
|
||||
verinum*lval = lsb_->eval_const(des, scope);
|
||||
assert(lval);
|
||||
switch (sel_) {
|
||||
default:
|
||||
cerr << get_line() << ": internal error: "
|
||||
<< "Unexpected sel_ value = " << sel_ << endl;
|
||||
assert(0);
|
||||
break;
|
||||
|
||||
midx = sig->sb_to_idx(mval->as_long());
|
||||
lidx = sig->sb_to_idx(lval->as_long());
|
||||
case PEIdent::SEL_IDX_DO:
|
||||
case PEIdent::SEL_IDX_UP: {
|
||||
assert(msb_);
|
||||
assert(lsb_);
|
||||
assert(idx_.empty());
|
||||
|
||||
/* Detect reversed indices of a part select. */
|
||||
if (lidx > midx) {
|
||||
cerr << get_line() << ": error: Part select "
|
||||
<< sig->name() << "[" << mval->as_long() << ":"
|
||||
<< lval->as_long() << "] indices reversed." << endl;
|
||||
cerr << get_line() << ": : Did you mean "
|
||||
<< sig->name() << "[" << lval->as_long() << ":"
|
||||
<< mval->as_long() << "]?" << endl;
|
||||
unsigned tmp = midx;
|
||||
midx = lidx;
|
||||
lidx = tmp;
|
||||
des->errors += 1;
|
||||
}
|
||||
NetExpr*tmp_ex = elab_and_eval(des, scope, msb_, -1);
|
||||
NetEConst*tmp = dynamic_cast<NetEConst*>(tmp_ex);
|
||||
assert(tmp);
|
||||
|
||||
/* Detect a part select out of range. */
|
||||
if (midx >= sig->vector_width()) {
|
||||
cerr << get_line() << ": error: Part select "
|
||||
<< sig->name() << "[" << mval->as_long() << ":"
|
||||
<< lval->as_long() << "] out of range." << endl;
|
||||
long midx_val = tmp->value().as_long();
|
||||
midx = sig->sb_to_idx(midx_val);
|
||||
delete tmp_ex;
|
||||
|
||||
tmp_ex = elab_and_eval(des, scope, lsb_, -1);
|
||||
tmp = dynamic_cast<NetEConst*>(tmp_ex);
|
||||
assert(tmp);
|
||||
|
||||
long wid = tmp->value().as_long();
|
||||
delete tmp_ex;
|
||||
|
||||
if (sel_ == PEIdent::SEL_IDX_UP)
|
||||
lidx = sig->sb_to_idx(midx_val+wid-1);
|
||||
else
|
||||
lidx = sig->sb_to_idx(midx_val-wid+1);
|
||||
|
||||
if (midx < lidx) {
|
||||
long tmp = midx;
|
||||
midx = lidx;
|
||||
lidx = tmp;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case PEIdent::SEL_PART: {
|
||||
assert(msb_);
|
||||
assert(lsb_);
|
||||
assert(idx_.empty());
|
||||
|
||||
NetExpr*tmp_ex = elab_and_eval(des, scope, msb_, -1);
|
||||
NetEConst*tmp = dynamic_cast<NetEConst*>(tmp_ex);
|
||||
assert(tmp);
|
||||
|
||||
long midx_val = tmp->value().as_long();
|
||||
midx = sig->sb_to_idx(midx_val);
|
||||
delete tmp_ex;
|
||||
|
||||
tmp_ex = elab_and_eval(des, scope, lsb_, -1);
|
||||
tmp = dynamic_cast<NetEConst*>(tmp_ex);
|
||||
assert(tmp);
|
||||
|
||||
long lidx_val = tmp->value().as_long();
|
||||
lidx = sig->sb_to_idx(lidx_val);
|
||||
delete tmp_ex;
|
||||
|
||||
/* Detect reversed indices of a part select. */
|
||||
if (lidx > midx) {
|
||||
cerr << get_line() << ": error: Part select "
|
||||
<< sig->name() << "[" << midx_val << ":"
|
||||
<< lidx_val << "] indices reversed." << endl;
|
||||
cerr << get_line() << ": : Did you mean "
|
||||
<< sig->name() << "[" << lidx_val << ":"
|
||||
<< midx_val << "]?" << endl;
|
||||
unsigned tmp = midx;
|
||||
midx = lidx;
|
||||
lidx = tmp;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
/* Detect a part select out of range. */
|
||||
if (midx >= sig->vector_width()) {
|
||||
cerr << get_line() << ": error: Part select "
|
||||
<< sig->name() << "[" << midx_val << ":"
|
||||
<< midx_val << "] out of range." << endl;
|
||||
midx = sig->vector_width() - 1;
|
||||
lidx = 0;
|
||||
des->errors += 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case PEIdent::SEL_NONE:
|
||||
if (!idx_.empty()) {
|
||||
assert(msb_ == 0);
|
||||
assert(lsb_ == 0);
|
||||
assert(idx_.size() == 1);
|
||||
verinum*mval = idx_[0]->eval_const(des, scope);
|
||||
if (mval == 0) {
|
||||
cerr << get_line() << ": error: Index of " << path_ <<
|
||||
" needs to be constant in this context." <<
|
||||
endl;
|
||||
cerr << get_line() << ": : Index expression is: "
|
||||
<< *(idx_[0]) << endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
assert(mval);
|
||||
|
||||
midx = sig->sb_to_idx(mval->as_long());
|
||||
if (midx >= sig->vector_width()) {
|
||||
cerr << get_line() << ": error: Index " << sig->name()
|
||||
<< "[" << mval->as_long() << "] out of range."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
midx = 0;
|
||||
}
|
||||
lidx = midx;
|
||||
|
||||
} else {
|
||||
if (msb_ || lsb_) {
|
||||
cerr << get_line() << ": internal error: "
|
||||
<< "Unexpected msb_/lsb_ values?" << endl;
|
||||
if (msb_)
|
||||
cerr << get_line() << " : "
|
||||
<< *msb_ << endl;
|
||||
if (lsb_)
|
||||
cerr << get_line() << " : "
|
||||
<< *lsb_ << endl;
|
||||
}
|
||||
assert(msb_ == 0 && lsb_ == 0);
|
||||
midx = sig->vector_width() - 1;
|
||||
lidx = 0;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
} else if (!idx_.empty()) {
|
||||
assert(msb_ == 0);
|
||||
assert(lsb_ == 0);
|
||||
assert(idx_.size() == 1);
|
||||
verinum*mval = idx_[0]->eval_const(des, scope);
|
||||
if (mval == 0) {
|
||||
cerr << get_line() << ": error: Index of " << path_ <<
|
||||
" needs to be constant in this context." <<
|
||||
endl;
|
||||
cerr << get_line() << ": : Index expression is: "
|
||||
<< *(idx_[0]) << endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
assert(mval);
|
||||
|
||||
midx = sig->sb_to_idx(mval->as_long());
|
||||
if (midx >= sig->vector_width()) {
|
||||
cerr << get_line() << ": error: Index " << sig->name()
|
||||
<< "[" << mval->as_long() << "] out of range."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
midx = 0;
|
||||
}
|
||||
lidx = midx;
|
||||
|
||||
} else {
|
||||
assert(msb_ == 0 && lsb_ == 0);
|
||||
midx = sig->vector_width() - 1;
|
||||
lidx = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -2296,6 +2454,7 @@ NetNet* PEString::elaborate_net(Design*des, NetScope*scope,
|
||||
net = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, strbits);
|
||||
}
|
||||
net->data_type(IVL_VT_BOOL);
|
||||
net->local_flag(true);
|
||||
|
||||
/* Make a verinum that is filled with the 0 pad. */
|
||||
@@ -2396,6 +2555,7 @@ NetNet* PETernary::elaborate_net(Design*des, NetScope*scope,
|
||||
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, 1);
|
||||
tmp->data_type(IVL_VT_LOGIC);
|
||||
tmp->local_flag(true);
|
||||
connect(log->pin(0), tmp->pin(0));
|
||||
|
||||
@@ -2406,7 +2566,10 @@ NetNet* PETernary::elaborate_net(Design*des, NetScope*scope,
|
||||
|
||||
/* This is the width of the LPM_MUX device that I'm about to
|
||||
create. It may be smaller then the desired output, but I'll
|
||||
handle padding below.
|
||||
handle padding below. Note that in principle the
|
||||
alternatives should be padded to the output width first,
|
||||
but it is more efficient to pad them only just enough to
|
||||
prevent loss, and do the finished padding later.
|
||||
|
||||
Create a NetNet object wide enough to hold the
|
||||
result. Also, pad the result values (if necessary) so that
|
||||
@@ -2415,7 +2578,7 @@ NetNet* PETernary::elaborate_net(Design*des, NetScope*scope,
|
||||
unsigned dwidth = (iwidth > width)? width : iwidth;
|
||||
|
||||
NetNet*sig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, width);
|
||||
NetNet::WIRE, dwidth);
|
||||
sig->data_type(expr_type);
|
||||
sig->local_flag(true);
|
||||
|
||||
@@ -2446,6 +2609,7 @@ NetNet* PETernary::elaborate_net(Design*des, NetScope*scope,
|
||||
if (rise || fall || decay) {
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, dwidth);
|
||||
sig->data_type(expr_type);
|
||||
|
||||
NetBUFZ*tmpz = new NetBUFZ(scope, scope->local_symbol(), dwidth);
|
||||
tmpz->rise_time(rise);
|
||||
@@ -2466,10 +2630,18 @@ NetNet* PETernary::elaborate_net(Design*des, NetScope*scope,
|
||||
|
||||
/* If the MUX device result is too narrow to fill out the
|
||||
desired result, pad with zeros... */
|
||||
assert(dwidth == width);
|
||||
assert(dwidth <= width);
|
||||
|
||||
des->add_node(mux);
|
||||
|
||||
/* If the MUX device results is too narrow to fill out the
|
||||
desired result, then pad it. It is OK to have a too-narrow
|
||||
result here because the dwidth choise is >= the width of
|
||||
both alternatives. Thus, padding here is equivilent to
|
||||
padding inside, and is cheaper. */
|
||||
if (dwidth < width)
|
||||
sig = pad_to_width(des, sig, width);
|
||||
|
||||
return sig;
|
||||
}
|
||||
|
||||
@@ -2580,6 +2752,11 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
|
||||
reduction=true; rtype = NetUReduce::XNOR; break;
|
||||
|
||||
case '-': // Unary 2's complement.
|
||||
// If this expression is self determined, get its width
|
||||
// from the sub_expression.
|
||||
if (owidth == 0)
|
||||
owidth = sub_sig->vector_width();
|
||||
|
||||
sig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, owidth);
|
||||
sig->data_type(sub_sig->data_type());
|
||||
@@ -2624,6 +2801,7 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
|
||||
NetNet*tmp_sig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE,
|
||||
sub_sig->vector_width());
|
||||
tmp_sig->data_type(sub_sig->data_type());
|
||||
tmp_sig->local_flag(true);
|
||||
|
||||
connect(tmp_sig->pin(0), sub->pin_DataA());
|
||||
@@ -2662,6 +2840,38 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
|
||||
|
||||
/*
|
||||
* $Log: elab_net.cc,v $
|
||||
* Revision 1.189 2006/08/08 05:11:37 steve
|
||||
* Handle 64bit delay constants.
|
||||
*
|
||||
* Revision 1.188 2006/06/20 05:06:47 steve
|
||||
* Sign extend operands of signed addition.
|
||||
*
|
||||
* Revision 1.187 2006/06/18 04:15:50 steve
|
||||
* Add support for system functions in continuous assignments.
|
||||
*
|
||||
* Revision 1.186 2006/06/02 04:48:50 steve
|
||||
* Make elaborate_expr methods aware of the width that the context
|
||||
* requires of it. In the process, fix sizing of the width of unary
|
||||
* minus is context determined sizes.
|
||||
*
|
||||
* Revision 1.185 2006/05/19 04:44:55 steve
|
||||
* Get self-determined unary - width right.
|
||||
*
|
||||
* Revision 1.184 2006/05/01 20:47:58 steve
|
||||
* More explicit datatype setup.
|
||||
*
|
||||
* Revision 1.183 2006/04/30 05:17:48 steve
|
||||
* Get the data type of part select results right.
|
||||
*
|
||||
* Revision 1.182 2006/04/28 05:09:51 steve
|
||||
* Handle padding of MUX net results.
|
||||
*
|
||||
* Revision 1.181 2006/04/28 04:28:35 steve
|
||||
* Allow concatenations as arguments to inout ports.
|
||||
*
|
||||
* Revision 1.180 2006/04/24 05:15:07 steve
|
||||
* Fix support for indexed part select in continuous assign l-values.
|
||||
*
|
||||
* Revision 1.179 2006/04/10 00:32:14 steve
|
||||
* Clean up index expression error message.
|
||||
*
|
||||
|
||||
+9
-4
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: elab_pexpr.cc,v 1.23 2006/02/02 02:43:58 steve Exp $"
|
||||
#ident "$Id: elab_pexpr.cc,v 1.24 2006/06/02 04:48:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -119,7 +119,7 @@ NetEConcat* PEConcat::elaborate_pexpr(Design*des, NetScope*scope) const
|
||||
|
||||
NetExpr*PEFNumber::elaborate_pexpr(Design*des, NetScope*scope) const
|
||||
{
|
||||
return elaborate_expr(des, scope);
|
||||
return elaborate_expr(des, scope, -1, false);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -181,13 +181,13 @@ NetExpr*PEIdent::elaborate_pexpr(Design*des, NetScope*scope) const
|
||||
*/
|
||||
NetExpr*PENumber::elaborate_pexpr(Design*des, NetScope*sc) const
|
||||
{
|
||||
return elaborate_expr(des, sc);
|
||||
return elaborate_expr(des, sc, -1, false);
|
||||
}
|
||||
|
||||
|
||||
NetEConst* PEString::elaborate_pexpr(Design*des, NetScope*scope) const
|
||||
{
|
||||
return elaborate_expr(des, scope);
|
||||
return elaborate_expr(des, scope, -1, false);
|
||||
}
|
||||
|
||||
NetETernary* PETernary::elaborate_pexpr(Design*des, NetScope*scope) const
|
||||
@@ -236,6 +236,11 @@ NetExpr*PEUnary::elaborate_pexpr (Design*des, NetScope*scope) const
|
||||
|
||||
/*
|
||||
* $Log: elab_pexpr.cc,v $
|
||||
* Revision 1.24 2006/06/02 04:48:50 steve
|
||||
* Make elaborate_expr methods aware of the width that the context
|
||||
* requires of it. In the process, fix sizing of the width of unary
|
||||
* minus is context determined sizes.
|
||||
*
|
||||
* Revision 1.23 2006/02/02 02:43:58 steve
|
||||
* Allow part selects of memory words in l-values.
|
||||
*
|
||||
|
||||
+25
-11
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: elab_scope.cc,v 1.39 2006/04/10 00:37:42 steve Exp $"
|
||||
#ident "$Id: elab_scope.cc,v 1.41 2006/06/02 04:48:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -325,7 +325,7 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
|
||||
// The initial value for the genvar does not need (nor can it
|
||||
// use) the genvar itself, so we can evaluate this expression
|
||||
// the same way any other paramter value is evaluated.
|
||||
NetExpr*init_ex = elab_and_eval(des, container, loop_init);
|
||||
NetExpr*init_ex = elab_and_eval(des, container, loop_init, -1);
|
||||
NetEConst*init = dynamic_cast<NetEConst*> (init_ex);
|
||||
if (init == 0) {
|
||||
cerr << get_line() << ": error: Cannot evaluate genvar"
|
||||
@@ -342,9 +342,10 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
|
||||
|
||||
container->genvar_tmp = loop_index;
|
||||
container->genvar_tmp_val = 0;
|
||||
verinum*test = loop_test->eval_const(des, container);
|
||||
NetExpr*test_ex = elab_and_eval(des, container, loop_test, -1);
|
||||
NetEConst*test = dynamic_cast<NetEConst*>(test_ex);
|
||||
assert(test);
|
||||
while (test->as_long()) {
|
||||
while (test->value().as_long()) {
|
||||
|
||||
// The actual name of the scope includes the genvar so
|
||||
// that each instance has a unique name in the
|
||||
@@ -378,19 +379,24 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
|
||||
scope_list_.push_back(scope);
|
||||
|
||||
// Calculate the step for the loop variable.
|
||||
verinum*step = loop_step->eval_const(des, container);
|
||||
NetExpr*step_ex = elab_and_eval(des, container, loop_step, -1);
|
||||
NetEConst*step = dynamic_cast<NetEConst*>(step_ex);
|
||||
assert(step);
|
||||
if (debug_elaborate)
|
||||
cerr << get_line() << ": debug: genvar step from "
|
||||
<< genvar << " to " << step->as_long() << endl;
|
||||
<< genvar << " to " << step->value().as_long() << endl;
|
||||
|
||||
genvar = step->as_long();
|
||||
genvar = step->value().as_long();
|
||||
container->genvar_tmp_val = genvar;
|
||||
delete step;
|
||||
delete test;
|
||||
test = loop_test->eval_const(des, container);
|
||||
delete test_ex;
|
||||
test_ex = elab_and_eval(des, container, loop_test, -1);
|
||||
test = dynamic_cast<NetEConst*>(test_ex);
|
||||
assert(test);
|
||||
}
|
||||
|
||||
// Clear the genvar_tmp field in the scope to reflect that the
|
||||
// genvar is no longer value for evaluating expressions.
|
||||
container->genvar_tmp = perm_string();
|
||||
|
||||
return true;
|
||||
@@ -442,8 +448,8 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
|
||||
return;
|
||||
}
|
||||
|
||||
NetExpr*mse = msb_ ? elab_and_eval(des, sc, msb_) : 0;
|
||||
NetExpr*lse = lsb_ ? elab_and_eval(des, sc, lsb_) : 0;
|
||||
NetExpr*mse = msb_ ? elab_and_eval(des, sc, msb_, -1) : 0;
|
||||
NetExpr*lse = lsb_ ? elab_and_eval(des, sc, lsb_, -1) : 0;
|
||||
NetEConst*msb = dynamic_cast<NetEConst*> (mse);
|
||||
NetEConst*lsb = dynamic_cast<NetEConst*> (lse);
|
||||
|
||||
@@ -742,6 +748,14 @@ void PWhile::elaborate_scope(Design*des, NetScope*scope) const
|
||||
|
||||
/*
|
||||
* $Log: elab_scope.cc,v $
|
||||
* Revision 1.41 2006/06/02 04:48:50 steve
|
||||
* Make elaborate_expr methods aware of the width that the context
|
||||
* requires of it. In the process, fix sizing of the width of unary
|
||||
* minus is context determined sizes.
|
||||
*
|
||||
* Revision 1.40 2006/04/12 05:05:03 steve
|
||||
* Use elab_and_eval to evaluate genvar expressions.
|
||||
*
|
||||
* Revision 1.39 2006/04/10 00:37:42 steve
|
||||
* Add support for generate loops w/ wires and gates.
|
||||
*
|
||||
|
||||
+12
-7
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: elab_sig.cc,v 1.41 2006/04/10 00:37:42 steve Exp $"
|
||||
#ident "$Id: elab_sig.cc,v 1.42 2006/06/02 04:48:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -318,10 +318,10 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
||||
case PTF_REG:
|
||||
if (return_type_.range) {
|
||||
NetExpr*me = elab_and_eval(des, scope,
|
||||
(*return_type_.range)[0]);
|
||||
(*return_type_.range)[0], -1);
|
||||
assert(me);
|
||||
NetExpr*le = elab_and_eval(des, scope,
|
||||
(*return_type_.range)[1]);
|
||||
(*return_type_.range)[1], -1);
|
||||
assert(le);
|
||||
|
||||
long mnum = 0, lnum = 0;
|
||||
@@ -548,7 +548,7 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
}
|
||||
|
||||
NetEConst*tmp;
|
||||
NetExpr*texpr = elab_and_eval(des, scope, msb_[idx]);
|
||||
NetExpr*texpr = elab_and_eval(des, scope, msb_[idx], -1);
|
||||
|
||||
tmp = dynamic_cast<NetEConst*>(texpr);
|
||||
if (tmp == 0) {
|
||||
@@ -562,7 +562,7 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
mnum[idx] = tmp->value().as_long();
|
||||
delete texpr;
|
||||
|
||||
texpr = elab_and_eval(des, scope, lsb_[idx]);
|
||||
texpr = elab_and_eval(des, scope, lsb_[idx], -1);
|
||||
tmp = dynamic_cast<NetEConst*>(texpr);
|
||||
if (tmp == 0) {
|
||||
cerr << msb_[idx]->get_line() << ": error: "
|
||||
@@ -623,8 +623,8 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
if (lidx_ || ridx_) {
|
||||
assert(lidx_ && ridx_);
|
||||
|
||||
NetExpr*lexp = elab_and_eval(des, scope, lidx_);
|
||||
NetExpr*rexp = elab_and_eval(des, scope, ridx_);
|
||||
NetExpr*lexp = elab_and_eval(des, scope, lidx_, -1);
|
||||
NetExpr*rexp = elab_and_eval(des, scope, ridx_, -1);
|
||||
|
||||
if ((lexp == 0) || (rexp == 0)) {
|
||||
cerr << get_line() << ": internal error: There is "
|
||||
@@ -720,6 +720,11 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
|
||||
/*
|
||||
* $Log: elab_sig.cc,v $
|
||||
* Revision 1.42 2006/06/02 04:48:50 steve
|
||||
* Make elaborate_expr methods aware of the width that the context
|
||||
* requires of it. In the process, fix sizing of the width of unary
|
||||
* minus is context determined sizes.
|
||||
*
|
||||
* Revision 1.41 2006/04/10 00:37:42 steve
|
||||
* Add support for generate loops w/ wires and gates.
|
||||
*
|
||||
|
||||
+67
-28
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: elaborate.cc,v 1.336 2006/04/10 00:37:42 steve Exp $"
|
||||
#ident "$Id: elaborate.cc,v 1.341 2006/08/08 05:11:37 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -267,6 +267,22 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
|
||||
if (lval->vector_width() > rval->vector_width())
|
||||
rval = pad_to_width(des, rval, lval->vector_width());
|
||||
|
||||
/* If, on the other hand, the r-value insists on being
|
||||
LARGER then the l-value, use a part select to chop it down
|
||||
down to size. */
|
||||
if (lval->vector_width() < rval->vector_width()) {
|
||||
NetPartSelect*tmp = new NetPartSelect(rval, 0,lval->vector_width(),
|
||||
NetPartSelect::VP);
|
||||
des->add_node(tmp);
|
||||
tmp->set_line(*this);
|
||||
NetNet*osig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::TRI, lval->vector_width());
|
||||
osig->set_line(*this);
|
||||
osig->data_type(rval->data_type());
|
||||
connect(osig->pin(0), tmp->pin(0));
|
||||
rval = osig;
|
||||
}
|
||||
|
||||
connect(lval->pin(0), rval->pin(0));
|
||||
|
||||
if (lval->local_flag())
|
||||
@@ -292,8 +308,8 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
|
||||
gates, then I am expected to make more then one
|
||||
gate. Figure out how many are desired. */
|
||||
if (msb_) {
|
||||
NetExpr*msb_exp = elab_and_eval(des, scope, msb_);
|
||||
NetExpr*lsb_exp = elab_and_eval(des, scope, lsb_);
|
||||
NetExpr*msb_exp = elab_and_eval(des, scope, msb_, -1);
|
||||
NetExpr*lsb_exp = elab_and_eval(des, scope, lsb_, -1);
|
||||
|
||||
NetEConst*msb_con = dynamic_cast<NetEConst*>(msb_exp);
|
||||
NetEConst*lsb_con = dynamic_cast<NetEConst*>(lsb_exp);
|
||||
@@ -520,6 +536,7 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
|
||||
|
||||
sig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, instance_width);
|
||||
sig->data_type(IVL_VT_LOGIC);
|
||||
sig->local_flag(true);
|
||||
sig->set_line(*this);
|
||||
connect(rep->pin(0), sig->pin(0));
|
||||
@@ -556,6 +573,8 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
|
||||
NetNet*tmp2 = new NetNet(scope,
|
||||
scope->local_symbol(),
|
||||
NetNet::WIRE, 1);
|
||||
tmp2->local_flag(true);
|
||||
tmp2->data_type(IVL_VT_LOGIC);
|
||||
connect(cc->pin(gdx+1), tmp2->pin(0));
|
||||
}
|
||||
|
||||
@@ -569,6 +588,8 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
|
||||
connect(tmp1->pin(1), sig->pin(0));
|
||||
NetNet*tmp2 = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, 1);
|
||||
tmp2->local_flag(true);
|
||||
tmp2->data_type(sig->data_type());
|
||||
connect(tmp1->pin(0), tmp2->pin(0));
|
||||
connect(cur[gdx]->pin(idx), tmp1->pin(0));
|
||||
}
|
||||
@@ -1312,7 +1333,7 @@ NetAssign_* PAssign_::elaborate_lval(Design*des, NetScope*scope) const
|
||||
*/
|
||||
static NetExpr*elaborate_delay_expr(PExpr*expr, Design*des, NetScope*scope)
|
||||
{
|
||||
NetExpr*dex = elab_and_eval(des, scope, expr);
|
||||
NetExpr*dex = elab_and_eval(des, scope, expr, -1);
|
||||
|
||||
/* If the delay expression is a real constant or vector
|
||||
constant, then evaluate it, scale it to the local time
|
||||
@@ -1322,7 +1343,7 @@ static NetExpr*elaborate_delay_expr(PExpr*expr, Design*des, NetScope*scope)
|
||||
verireal fn = tmp->value();
|
||||
|
||||
int shift = scope->time_unit() - des->get_precision();
|
||||
long delay = fn.as_long(shift);
|
||||
int64_t delay = fn.as_long64(shift);
|
||||
if (delay < 0)
|
||||
delay = 0;
|
||||
|
||||
@@ -1334,8 +1355,8 @@ static NetExpr*elaborate_delay_expr(PExpr*expr, Design*des, NetScope*scope)
|
||||
if (NetEConst*tmp = dynamic_cast<NetEConst*>(dex)) {
|
||||
verinum fn = tmp->value();
|
||||
|
||||
unsigned long delay =
|
||||
des->scale_to_precision(fn.as_ulong(), scope);
|
||||
uint64_t delay =
|
||||
des->scale_to_precision(fn.as_ulong64(), scope);
|
||||
|
||||
delete tmp;
|
||||
return new NetEConst(verinum(delay));
|
||||
@@ -1347,7 +1368,7 @@ static NetExpr*elaborate_delay_expr(PExpr*expr, Design*des, NetScope*scope)
|
||||
return that expression. */
|
||||
int shift = scope->time_unit() - des->get_precision();
|
||||
if (shift > 0) {
|
||||
unsigned long scale = 1;
|
||||
uint64_t scale = 1;
|
||||
while (shift > 0) {
|
||||
scale *= 10;
|
||||
shift -= 1;
|
||||
@@ -1389,7 +1410,7 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
|
||||
/* Elaborate the r-value expression, then try to evaluate it. */
|
||||
|
||||
assert(rval());
|
||||
NetExpr*rv = elab_and_eval(des, scope, rval());
|
||||
NetExpr*rv = elab_and_eval(des, scope, rval(), lv->lwidth());
|
||||
if (rv == 0) return 0;
|
||||
assert(rv);
|
||||
|
||||
@@ -1427,6 +1448,7 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::REG, wid);
|
||||
tmp->set_line(*this);
|
||||
tmp->data_type(rv->expr_type());
|
||||
|
||||
NetESignal*sig = new NetESignal(tmp);
|
||||
|
||||
@@ -1508,7 +1530,7 @@ NetProc* PAssignNB::elaborate(Design*des, NetScope*scope) const
|
||||
assert(rval());
|
||||
|
||||
/* Elaborate and precalculate the r-value. */
|
||||
NetExpr*rv = elab_and_eval(des, scope, rval());
|
||||
NetExpr*rv = elab_and_eval(des, scope, rval(), count_lval_width(lv));
|
||||
if (rv == 0)
|
||||
return 0;
|
||||
|
||||
@@ -1616,7 +1638,7 @@ NetProc* PCase::elaborate(Design*des, NetScope*scope) const
|
||||
{
|
||||
assert(scope);
|
||||
|
||||
NetExpr*expr = elab_and_eval(des, scope, expr_);
|
||||
NetExpr*expr = elab_and_eval(des, scope, expr_, -1);
|
||||
if (expr == 0) {
|
||||
cerr << get_line() << ": error: Unable to elaborate this case"
|
||||
" expression." << endl;
|
||||
@@ -1668,7 +1690,7 @@ NetProc* PCase::elaborate(Design*des, NetScope*scope) const
|
||||
NetExpr*gu = 0;
|
||||
NetProc*st = 0;
|
||||
assert(cur->expr[e]);
|
||||
gu = elab_and_eval(des, scope, cur->expr[e]);
|
||||
gu = elab_and_eval(des, scope, cur->expr[e], -1);
|
||||
|
||||
if (cur->stat)
|
||||
st = cur->stat->elaborate(des, scope);
|
||||
@@ -1686,7 +1708,7 @@ NetProc* PCondit::elaborate(Design*des, NetScope*scope) const
|
||||
assert(scope);
|
||||
|
||||
// Elaborate and try to evaluate the conditional expression.
|
||||
NetExpr*expr = elab_and_eval(des, scope, expr_);
|
||||
NetExpr*expr = elab_and_eval(des, scope, expr_, -1);
|
||||
if (expr == 0) {
|
||||
cerr << get_line() << ": error: Unable to elaborate"
|
||||
" condition expression." << endl;
|
||||
@@ -1793,7 +1815,7 @@ NetProc* PCallTask::elaborate_sys(Design*des, NetScope*scope) const
|
||||
|
||||
for (unsigned idx = 0 ; idx < parm_count ; idx += 1) {
|
||||
PExpr*ex = parm(idx);
|
||||
eparms[idx] = ex? ex->elaborate_expr(des, scope, true) : 0;
|
||||
eparms[idx] = ex? ex->elaborate_expr(des, scope, -1, true) : 0;
|
||||
|
||||
/* Attempt to pre-evaluate the parameters. It may be
|
||||
possible to at least partially reduce the
|
||||
@@ -1907,7 +1929,7 @@ NetProc* PCallTask::elaborate_usr(Design*des, NetScope*scope) const
|
||||
NetAssign_*lv = new NetAssign_(port);
|
||||
unsigned wid = count_lval_width(lv);
|
||||
|
||||
NetExpr*rv = elab_and_eval(des, scope, parms_[idx]);
|
||||
NetExpr*rv = elab_and_eval(des, scope, parms_[idx], wid);
|
||||
rv->set_width(wid);
|
||||
rv = pad_to_width(rv, wid);
|
||||
NetAssign*pr = new NetAssign(lv, rv);
|
||||
@@ -1987,12 +2009,12 @@ NetCAssign* PCAssign::elaborate(Design*des, NetScope*scope) const
|
||||
if (lval == 0)
|
||||
return 0;
|
||||
|
||||
NetExpr*rexp = elab_and_eval(des, scope, expr_);
|
||||
unsigned lwid = count_lval_width(lval);
|
||||
|
||||
NetExpr*rexp = elab_and_eval(des, scope, expr_, lwid);
|
||||
if (rexp == 0)
|
||||
return 0;
|
||||
|
||||
unsigned lwid = count_lval_width(lval);
|
||||
|
||||
rexp->set_width(lwid);
|
||||
rexp = pad_to_width(rexp, lwid);
|
||||
|
||||
@@ -2041,7 +2063,7 @@ NetProc* PDelayStatement::elaborate(Design*des, NetScope*scope) const
|
||||
|
||||
if (NetEConst*tmp = dynamic_cast<NetEConst*>(dex)) {
|
||||
if (statement_)
|
||||
return new NetPDelay(tmp->value().as_ulong(),
|
||||
return new NetPDelay(tmp->value().as_ulong64(),
|
||||
statement_->elaborate(des, scope));
|
||||
else
|
||||
return new NetPDelay(tmp->value().as_ulong(), 0);
|
||||
@@ -2335,7 +2357,7 @@ NetProc* PEventStatement::elaborate_wait(Design*des, NetScope*scope,
|
||||
|
||||
/* Elaborate wait expression. Don't eval yet, we will do that
|
||||
shortly, after we apply a reduction or. */
|
||||
NetExpr*expr = pe->elaborate_expr(des, scope);
|
||||
NetExpr*expr = pe->elaborate_expr(des, scope, -1, false);
|
||||
if (expr == 0) {
|
||||
cerr << get_line() << ": error: Unable to elaborate"
|
||||
" wait condition expression." << endl;
|
||||
@@ -2515,12 +2537,12 @@ NetForce* PForce::elaborate(Design*des, NetScope*scope) const
|
||||
if (lval == 0)
|
||||
return 0;
|
||||
|
||||
NetExpr*rexp = elab_and_eval(des, scope, expr_);
|
||||
unsigned lwid = count_lval_width(lval);
|
||||
|
||||
NetExpr*rexp = elab_and_eval(des, scope, expr_, lwid);
|
||||
if (rexp == 0)
|
||||
return 0;
|
||||
|
||||
unsigned lwid = count_lval_width(lval);
|
||||
|
||||
rexp->set_width(lwid, true);
|
||||
rexp = pad_to_width(rexp, lwid);
|
||||
|
||||
@@ -2578,7 +2600,7 @@ NetProc* PForStatement::elaborate(Design*des, NetScope*scope) const
|
||||
|
||||
/* Make the r-value of the initial assignment, and size it
|
||||
properly. Then use it to build the assignment statement. */
|
||||
etmp = elab_and_eval(des, scope, expr1_);
|
||||
etmp = elab_and_eval(des, scope, expr1_, lv->lwidth());
|
||||
etmp->set_width(lv->lwidth());
|
||||
etmp = pad_to_width(etmp, lv->lwidth());
|
||||
|
||||
@@ -2621,7 +2643,7 @@ NetProc* PForStatement::elaborate(Design*des, NetScope*scope) const
|
||||
|
||||
/* Make the rvalue of the increment expression, and size it
|
||||
for the lvalue. */
|
||||
etmp = expr2_->elaborate_expr(des, scope);
|
||||
etmp = expr2_->elaborate_expr(des, scope, lv->lwidth(), false);
|
||||
etmp->set_width(lv->lwidth());
|
||||
NetAssign*step = new NetAssign(lv, etmp);
|
||||
step->set_line(*this);
|
||||
@@ -2632,7 +2654,7 @@ NetProc* PForStatement::elaborate(Design*des, NetScope*scope) const
|
||||
/* Elaborate the condition expression. Try to evaluate it too,
|
||||
in case it is a constant. This is an interesting case
|
||||
worthy of a warning. */
|
||||
NetExpr*ce = elab_and_eval(des, scope, cond_);
|
||||
NetExpr*ce = elab_and_eval(des, scope, cond_, -1);
|
||||
if (ce == 0) {
|
||||
delete top;
|
||||
return 0;
|
||||
@@ -2713,7 +2735,7 @@ NetProc* PRepeat::elaborate(Design*des, NetScope*scope) const
|
||||
{
|
||||
assert(scope);
|
||||
|
||||
NetExpr*expr = elab_and_eval(des, scope, expr_);
|
||||
NetExpr*expr = elab_and_eval(des, scope, expr_, -1);
|
||||
if (expr == 0) {
|
||||
cerr << get_line() << ": Unable to elaborate"
|
||||
" repeat expression." << endl;
|
||||
@@ -2834,7 +2856,7 @@ NetProc* PTrigger::elaborate(Design*des, NetScope*scope) const
|
||||
*/
|
||||
NetProc* PWhile::elaborate(Design*des, NetScope*scope) const
|
||||
{
|
||||
NetWhile*loop = new NetWhile(elab_and_eval(des, scope, cond_),
|
||||
NetWhile*loop = new NetWhile(elab_and_eval(des, scope, cond_, -1),
|
||||
statement_->elaborate(des, scope));
|
||||
return loop;
|
||||
}
|
||||
@@ -3111,6 +3133,23 @@ Design* elaborate(list<perm_string>roots)
|
||||
|
||||
/*
|
||||
* $Log: elaborate.cc,v $
|
||||
* Revision 1.341 2006/08/08 05:11:37 steve
|
||||
* Handle 64bit delay constants.
|
||||
*
|
||||
* Revision 1.340 2006/06/02 04:48:50 steve
|
||||
* Make elaborate_expr methods aware of the width that the context
|
||||
* requires of it. In the process, fix sizing of the width of unary
|
||||
* minus is context determined sizes.
|
||||
*
|
||||
* Revision 1.339 2006/05/01 20:47:59 steve
|
||||
* More explicit datatype setup.
|
||||
*
|
||||
* Revision 1.338 2006/04/30 05:17:48 steve
|
||||
* Get the data type of part select results right.
|
||||
*
|
||||
* Revision 1.337 2006/04/26 04:43:50 steve
|
||||
* Chop down assign r-values that elaborate too wide.
|
||||
*
|
||||
* Revision 1.336 2006/04/10 00:37:42 steve
|
||||
* Add support for generate loops w/ wires and gates.
|
||||
*
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: emit.cc,v 1.86 2005/07/11 16:56:50 steve Exp $"
|
||||
#ident "$Id: emit.cc,v 1.87 2006/06/18 04:15:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -146,6 +146,10 @@ bool NetUReduce::emit_node(struct target_t*tgt) const
|
||||
return tgt->ureduce(this);
|
||||
}
|
||||
|
||||
bool NetSysFunc::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->net_sysfunction(this);
|
||||
}
|
||||
|
||||
bool NetUserFunc::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
@@ -525,6 +529,9 @@ int emit(const Design*des, const char*type)
|
||||
|
||||
/*
|
||||
* $Log: emit.cc,v $
|
||||
* Revision 1.87 2006/06/18 04:15:50 steve
|
||||
* Add support for system functions in continuous assignments.
|
||||
*
|
||||
* Revision 1.86 2005/07/11 16:56:50 steve
|
||||
* Remove NetVariable and ivl_variable_t structures.
|
||||
*
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: eval.cc,v 1.40 2006/04/10 00:37:42 steve Exp $"
|
||||
#ident "$Id: eval.cc,v 1.43 2006/08/08 05:11:37 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -150,7 +150,12 @@ verinum* PEConcat::eval_const(const Design*des, NetScope*scope) const
|
||||
return 0;
|
||||
|
||||
for (unsigned idx = 1 ; idx < parms_.count() ; idx += 1) {
|
||||
|
||||
verinum*tmp = parms_[idx]->eval_const(des, scope);
|
||||
if (tmp == 0) {
|
||||
delete accum;
|
||||
return 0;
|
||||
}
|
||||
assert(tmp);
|
||||
|
||||
*accum = concat(*accum, *tmp);
|
||||
@@ -254,7 +259,7 @@ verinum* PEUnary::eval_const(const Design*des, NetScope*scope) const
|
||||
/* We need to expand the value a bit if we are
|
||||
taking the 2's complement so that we are
|
||||
guaranteed to not overflow. */
|
||||
verinum tmp (0UL, val->len()+1);
|
||||
verinum tmp ((uint64_t)0, val->len()+1);
|
||||
for (unsigned idx = 0 ; idx < val->len() ; idx += 1)
|
||||
tmp.set(idx, val->get(idx));
|
||||
|
||||
@@ -271,6 +276,15 @@ verinum* PEUnary::eval_const(const Design*des, NetScope*scope) const
|
||||
|
||||
/*
|
||||
* $Log: eval.cc,v $
|
||||
* Revision 1.43 2006/08/08 05:11:37 steve
|
||||
* Handle 64bit delay constants.
|
||||
*
|
||||
* Revision 1.42 2006/05/19 04:07:24 steve
|
||||
* eval_const is not strict.
|
||||
*
|
||||
* Revision 1.41 2006/05/17 16:49:30 steve
|
||||
* Error message if concat expression cannot evaluate.
|
||||
*
|
||||
* Revision 1.40 2006/04/10 00:37:42 steve
|
||||
* Add support for generate loops w/ wires and gates.
|
||||
*
|
||||
|
||||
+78
-1
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: eval_tree.cc,v 1.68 2006/03/18 22:52:27 steve Exp $"
|
||||
#ident "$Id: eval_tree.cc,v 1.69 2006/07/31 03:50:17 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -937,6 +937,80 @@ NetExpr* NetEBMult::eval_tree()
|
||||
return new NetEConst(lval * rval);
|
||||
}
|
||||
|
||||
NetExpr* NetEBPow::eval_tree_real_()
|
||||
{
|
||||
verireal lval;
|
||||
verireal rval;
|
||||
|
||||
switch (left_->expr_type()) {
|
||||
case IVL_VT_REAL: {
|
||||
NetECReal*lc = dynamic_cast<NetECReal*> (left_);
|
||||
if (lc == 0) return 0;
|
||||
lval = lc->value();
|
||||
break;
|
||||
}
|
||||
|
||||
case IVL_VT_BOOL:
|
||||
case IVL_VT_LOGIC: {
|
||||
NetEConst*lc = dynamic_cast<NetEConst*>(left_);
|
||||
if (lc == 0) return 0;
|
||||
verinum tmp = lc->value();
|
||||
lval = verireal(tmp.as_long());
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
switch (right_->expr_type()) {
|
||||
case IVL_VT_REAL: {
|
||||
NetECReal*rc = dynamic_cast<NetECReal*> (right_);
|
||||
if (rc == 0) return 0;
|
||||
rval = rc->value();
|
||||
break;
|
||||
}
|
||||
|
||||
case IVL_VT_BOOL:
|
||||
case IVL_VT_LOGIC: {
|
||||
NetEConst*rc = dynamic_cast<NetEConst*>(right_);
|
||||
if (rc == 0) return 0;
|
||||
verinum tmp = rc->value();
|
||||
rval = verireal(tmp.as_long());
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
|
||||
NetECReal*res = new NetECReal( pow(lval,rval) );
|
||||
res->set_line(*this);
|
||||
return res;
|
||||
}
|
||||
|
||||
NetExpr* NetEBPow::eval_tree()
|
||||
{
|
||||
eval_sub_tree_();
|
||||
|
||||
if (expr_type() == IVL_VT_REAL)
|
||||
return eval_tree_real_();
|
||||
|
||||
assert(expr_type() == IVL_VT_LOGIC);
|
||||
|
||||
NetEConst*lc = dynamic_cast<NetEConst*>(left_);
|
||||
if (lc == 0) return 0;
|
||||
NetEConst*rc = dynamic_cast<NetEConst*>(right_);
|
||||
if (rc == 0) return 0;
|
||||
|
||||
verinum lval = lc->value();
|
||||
verinum rval = rc->value();
|
||||
|
||||
return new NetEConst( pow(lval,rval) );
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Evaluate the shift operator if possible. For this to work, both
|
||||
* operands must be constant.
|
||||
@@ -1589,6 +1663,9 @@ NetEConst* NetEUReduce::eval_tree()
|
||||
|
||||
/*
|
||||
* $Log: eval_tree.cc,v $
|
||||
* Revision 1.69 2006/07/31 03:50:17 steve
|
||||
* Add support for power in constant expressions.
|
||||
*
|
||||
* Revision 1.68 2006/03/18 22:52:27 steve
|
||||
* Properly handle signedness in compare.
|
||||
*
|
||||
|
||||
+72
-12
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: expr_synth.cc,v 1.74 2006/01/03 05:15:33 steve Exp $"
|
||||
#ident "$Id: expr_synth.cc,v 1.80 2006/08/08 05:11:37 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -57,6 +57,7 @@ NetNet* NetEBAdd::synthesize(Design*des)
|
||||
perm_string path = lsig->scope()->local_symbol();
|
||||
NetNet*osig = new NetNet(lsig->scope(), path, NetNet::IMPLICIT, width);
|
||||
osig->local_flag(true);
|
||||
osig->data_type(expr_type());
|
||||
|
||||
perm_string oname = osig->scope()->local_symbol();
|
||||
NetAddSub *adder = new NetAddSub(lsig->scope(), oname, width);
|
||||
@@ -107,6 +108,7 @@ NetNet* NetEBBits::synthesize(Design*des)
|
||||
NetNet*osig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, lsig->vector_width());
|
||||
osig->local_flag(true);
|
||||
osig->data_type(expr_type());
|
||||
|
||||
perm_string oname = scope->local_symbol();
|
||||
unsigned wid = lsig->vector_width();
|
||||
@@ -232,6 +234,14 @@ NetNet* NetEBComp::synthesize(Design*des)
|
||||
return osig;
|
||||
}
|
||||
|
||||
NetNet* NetEBPow::synthesize(Design*des)
|
||||
{
|
||||
cerr << get_line() << ": internal error: Do not yet know how to handle"
|
||||
<< " power operator in this context." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetNet* NetEBMult::synthesize(Design*des)
|
||||
{
|
||||
NetNet*lsig = left_->synthesize(des);
|
||||
@@ -260,7 +270,9 @@ NetNet* NetEBMult::synthesize(Design*des)
|
||||
|
||||
NetNet*osig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, expr_width());
|
||||
osig->data_type(lsig->data_type());
|
||||
osig->set_line(*this);
|
||||
osig->data_type(expr_type());
|
||||
osig->local_flag(true);
|
||||
|
||||
connect(mult->pin_Result(), osig->pin(0));
|
||||
@@ -341,6 +353,7 @@ NetNet* NetEBLogic::synthesize(Design*des)
|
||||
|
||||
NetNet*osig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, 1);
|
||||
osig->data_type(expr_type());
|
||||
osig->local_flag(true);
|
||||
|
||||
|
||||
@@ -433,6 +446,7 @@ NetNet* NetEBShift::synthesize(Design*des)
|
||||
|
||||
NetNet*osig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, expr_width());
|
||||
osig->data_type(expr_type());
|
||||
osig->local_flag(true);
|
||||
|
||||
unsigned long ushift = shift>=0? shift : -shift;
|
||||
@@ -454,6 +468,7 @@ NetNet* NetEBShift::synthesize(Design*des)
|
||||
|
||||
NetNet*zsig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, znum.len());
|
||||
zsig->data_type(osig->data_type());
|
||||
connect(zcon->pin(0), zsig->pin(0));
|
||||
|
||||
NetConcat*ccat = new NetConcat(scope, scope->local_symbol(),
|
||||
@@ -479,6 +494,7 @@ NetNet* NetEBShift::synthesize(Design*des)
|
||||
|
||||
NetNet*osig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, expr_width());
|
||||
osig->data_type(expr_type());
|
||||
osig->local_flag(true);
|
||||
|
||||
assert(op() == 'l');
|
||||
@@ -556,12 +572,28 @@ NetNet* NetEConst::synthesize(Design*des)
|
||||
return osig;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a NetLiteral object to represent real valued constants.
|
||||
*/
|
||||
NetNet* NetECReal::synthesize(Design*des)
|
||||
{
|
||||
cerr << get_line() << ": error: Real constants are "
|
||||
<< "not synthesizable." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
NetScope*scope = des->find_root_scope();
|
||||
assert(scope);
|
||||
|
||||
perm_string path = scope->local_symbol();
|
||||
|
||||
NetNet*osig = new NetNet(scope, path, NetNet::WIRE, 1);
|
||||
osig->local_flag(true);
|
||||
osig->data_type(IVL_VT_REAL);
|
||||
osig->set_signed(has_sign());
|
||||
osig->set_line(*this);
|
||||
|
||||
NetLiteral*con = new NetLiteral(scope, scope->local_symbol(), value_);
|
||||
des->add_node(con);
|
||||
con->set_line(*this);
|
||||
|
||||
connect(osig->pin(0), con->pin(0));
|
||||
return osig;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -578,6 +610,7 @@ NetNet* NetEUBits::synthesize(Design*des)
|
||||
unsigned width = isig->vector_width();
|
||||
NetNet*osig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, width);
|
||||
osig->data_type(expr_type());
|
||||
osig->local_flag(true);
|
||||
|
||||
perm_string oname = scope->local_symbol();
|
||||
@@ -608,6 +641,7 @@ NetNet* NetEUReduce::synthesize(Design*des)
|
||||
|
||||
NetNet*osig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, 1);
|
||||
osig->data_type(expr_type());
|
||||
osig->local_flag(true);
|
||||
|
||||
perm_string oname = scope->local_symbol();
|
||||
@@ -699,12 +733,15 @@ NetNet* NetESelect::synthesize(Design *des)
|
||||
|
||||
if (base_ != 0) {
|
||||
// For now, only handle constant part selects in this
|
||||
// context.
|
||||
// context. NOTE: the elaboration that created the
|
||||
// NetESelect already translated the part base to
|
||||
// canonical form, so the base_ is canonical already.
|
||||
NetEConst*bcon = dynamic_cast<NetEConst*>(base_);
|
||||
assert(bcon);
|
||||
|
||||
long bval = bcon->value().as_long();
|
||||
off = sub->sb_to_idx(bval);
|
||||
assert(bval >= 0);
|
||||
off = bval;
|
||||
}
|
||||
|
||||
/* If there is a part select, then generate a PartSelect node
|
||||
@@ -720,10 +757,12 @@ NetNet* NetESelect::synthesize(Design *des)
|
||||
sel->set_line(*this);
|
||||
des->add_node(sel);
|
||||
|
||||
sub = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, expr_width());
|
||||
sub->local_flag(true);
|
||||
sub->set_line(*this);
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, expr_width());
|
||||
tmp->data_type(sub->data_type());
|
||||
tmp->local_flag(true);
|
||||
tmp->set_line(*this);
|
||||
sub = tmp;
|
||||
connect(sub->pin(0), sel->pin(0));
|
||||
}
|
||||
|
||||
@@ -733,6 +772,7 @@ NetNet* NetESelect::synthesize(Design *des)
|
||||
|
||||
NetNet*net = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, expr_width());
|
||||
net->data_type(expr_type());
|
||||
if (has_sign()) {
|
||||
NetSignExtend*pad = new NetSignExtend(scope,
|
||||
scope->local_symbol(),
|
||||
@@ -752,7 +792,7 @@ NetNet* NetESelect::synthesize(Design *des)
|
||||
|
||||
assert(expr_width() > sub->vector_width());
|
||||
unsigned pad_width = expr_width() - sub->vector_width();
|
||||
verinum pad(0UL, pad_width);
|
||||
verinum pad((uint64_t)0, pad_width);
|
||||
NetConst*con = new NetConst(scope, scope->local_symbol(),
|
||||
pad);
|
||||
con->set_line(*this);
|
||||
@@ -760,6 +800,7 @@ NetNet* NetESelect::synthesize(Design *des)
|
||||
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, pad_width);
|
||||
tmp->data_type(expr_type());
|
||||
tmp->local_flag(true);
|
||||
tmp->set_line(*this);
|
||||
connect(tmp->pin(0), con->pin(0));
|
||||
@@ -790,6 +831,7 @@ NetNet* NetETernary::synthesize(Design *des)
|
||||
|
||||
unsigned width=expr_width();
|
||||
NetNet*osig = new NetNet(csig->scope(), path, NetNet::IMPLICIT, width);
|
||||
osig->data_type(expr_type());
|
||||
osig->local_flag(true);
|
||||
|
||||
/* Make sure both value operands are the right width. */
|
||||
@@ -848,6 +890,24 @@ NetNet* NetESignal::synthesize(Design*des)
|
||||
|
||||
/*
|
||||
* $Log: expr_synth.cc,v $
|
||||
* Revision 1.80 2006/08/08 05:11:37 steve
|
||||
* Handle 64bit delay constants.
|
||||
*
|
||||
* Revision 1.79 2006/07/31 03:50:17 steve
|
||||
* Add support for power in constant expressions.
|
||||
*
|
||||
* Revision 1.78 2006/07/08 21:48:46 steve
|
||||
* Handle real valued literals in net contexts.
|
||||
*
|
||||
* Revision 1.77 2006/05/01 20:47:59 steve
|
||||
* More explicit datatype setup.
|
||||
*
|
||||
* Revision 1.76 2006/05/01 05:40:21 steve
|
||||
* fix net type of multiply output.
|
||||
*
|
||||
* Revision 1.75 2006/04/30 05:17:48 steve
|
||||
* Get the data type of part select results right.
|
||||
*
|
||||
* Revision 1.74 2006/01/03 05:15:33 steve
|
||||
* Fix the return type of a synthesized divide.
|
||||
*
|
||||
|
||||
+39
-15
@@ -19,9 +19,11 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: ivl_target.h,v 1.166 2006/04/10 00:37:42 steve Exp $"
|
||||
#ident "$Id: ivl_target.h,v 1.170 2006/08/08 05:11:37 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define _BEGIN_DECL extern "C" {
|
||||
#define _END_DECL }
|
||||
@@ -244,6 +246,7 @@ typedef enum ivl_lpm_type_e {
|
||||
IVL_LPM_RE_XNOR= 24,
|
||||
IVL_LPM_RE_XOR = 25,
|
||||
IVL_LPM_REPEAT = 26,
|
||||
IVL_LPM_SFUNC = 29,
|
||||
IVL_LPM_SHIFTL = 6,
|
||||
IVL_LPM_SHIFTR = 7,
|
||||
IVL_LPM_SIGN_EXT=27,
|
||||
@@ -985,12 +988,29 @@ extern const char* ivl_udp_name(ivl_udp_t net);
|
||||
* input must be signed, and the output will be a vector sign extended
|
||||
* to the desired width. The ivl_lpm_width() value is the output
|
||||
* width, the input will be whatever it wants to be.
|
||||
*
|
||||
* - Shifts (IVL_LPM_SHIFTL/SHIFTR)
|
||||
* This node takes two inputs, a vector and a shift distance. The
|
||||
* ivl_lpm_data(0) nexus is the vector input, and the ivl_lpm_data(1)
|
||||
* the shift distance. The vector input is the same width as the
|
||||
* output, but the distance has its own width.
|
||||
*
|
||||
* The ivl_lpm_signed() flag means for IVL_LPM_SHIFTR that the right
|
||||
* shift is *signed*. For SHIFTL, then signed-ness is emaningless.
|
||||
*
|
||||
* - System function call (IVL_LPM_SFUNC)
|
||||
* This device represents a netlist call to a system function. The
|
||||
* inputs to the device are passed to a system function, and the
|
||||
* result is sent via the output. The ivl_lpm_q function returns the
|
||||
* output nexus.
|
||||
*
|
||||
* The ivl_lpm_size function returns the number of arguments, and the
|
||||
* ivl_lpm_data(net,N) returns the nexa for the argument.
|
||||
*
|
||||
* The ivl_lpm_string(net) function returns the name of the system
|
||||
* function (i.e. "$display") that was found in the source code. The
|
||||
* compiler does little checking of that name.
|
||||
*
|
||||
* - User Function Call (IVL_LPM_UFUNC)
|
||||
* This device is special as it represents a call to a user defined
|
||||
* function (behavioral code) within a netlist. The inputs to the
|
||||
@@ -1039,14 +1059,6 @@ extern ivl_nexus_t ivl_lpm_enable(ivl_lpm_t net);
|
||||
extern ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx);
|
||||
/* IVL_LPM_ADD IVL_LPM_MULT IVL_LPM_SUB */
|
||||
extern ivl_nexus_t ivl_lpm_datab(ivl_lpm_t net, unsigned idx);
|
||||
#if 0
|
||||
/* IVL_LPM_UFUNC */
|
||||
extern ivl_nexus_t ivl_lpm_data2(ivl_lpm_t net, unsigned sdx, unsigned idx);
|
||||
#endif
|
||||
#if 0
|
||||
/* IVL_LPM_UFUNC */
|
||||
extern unsigned ivl_lpm_data2_width(ivl_lpm_t net, unsigned sdx);
|
||||
#endif
|
||||
/* IVL_LPM_ADD IVL_LPM_FF IVL_LPM_MULT IVL_LPM_PART IVL_LPM_RAM
|
||||
IVL_LPM_SUB IVL_LPM_UFUNC */
|
||||
extern ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx);
|
||||
@@ -1056,6 +1068,8 @@ extern unsigned ivl_lpm_selects(ivl_lpm_t net);
|
||||
extern ivl_nexus_t ivl_lpm_select(ivl_lpm_t net);
|
||||
/* IVL_LPM_CONCAT IVL_LPM_MUX IVL_LPM_REPEAT IVL_LPM_UFUNC */
|
||||
extern unsigned ivl_lpm_size(ivl_lpm_t net);
|
||||
/* IVL_LPM_SFUNC */
|
||||
extern const char*ivl_lpm_string(ivl_lpm_t net);
|
||||
/* IVL_LPM_RAM */
|
||||
extern ivl_memory_t ivl_lpm_memory(ivl_lpm_t net);
|
||||
|
||||
@@ -1108,10 +1122,8 @@ extern ivl_memory_t ivl_lpm_memory(ivl_lpm_t net);
|
||||
* signal (or even 1) if only a part of the l-value signal is to be
|
||||
* assigned.
|
||||
*
|
||||
* The ivl_lval_part_off is the canonical base of a constant part or
|
||||
* bit select. If the bit select base is non-constant, then the
|
||||
* ivl_lval_mux will contain an expression. If there is a mux
|
||||
* expression, then the ivl_lval_part_off result can be ignored.
|
||||
* The ivl_lval_part_off is the canonical base of a part or
|
||||
* bit select.
|
||||
*
|
||||
* - Memory words
|
||||
* If the l-value is a memory word, the ivl_lval_mem function returns
|
||||
@@ -1122,7 +1134,7 @@ extern ivl_memory_t ivl_lpm_memory(ivl_lpm_t net);
|
||||
*/
|
||||
|
||||
extern unsigned ivl_lval_width(ivl_lval_t net);
|
||||
extern ivl_expr_t ivl_lval_mux(ivl_lval_t net);
|
||||
extern ivl_expr_t ivl_lval_mux(ivl_lval_t net); // XXXX Obsolete?
|
||||
extern ivl_expr_t ivl_lval_idx(ivl_lval_t net);
|
||||
extern ivl_memory_t ivl_lval_mem(ivl_lval_t net);
|
||||
extern ivl_expr_t ivl_lval_part_off(ivl_lval_t net);
|
||||
@@ -1648,7 +1660,7 @@ extern ivl_statement_t ivl_stmt_cond_true(ivl_statement_t net);
|
||||
/* IVL_ST_ASSIGN IVL_ST_ASSIGN_NB IVL_ST_DELAYX */
|
||||
extern ivl_expr_t ivl_stmt_delay_expr(ivl_statement_t net);
|
||||
/* IVL_ST_DELAY */
|
||||
extern unsigned long ivl_stmt_delay_val(ivl_statement_t net);
|
||||
extern uint64_t ivl_stmt_delay_val(ivl_statement_t net);
|
||||
/* IVL_ST_WAIT IVL_ST_TRIGGER */
|
||||
extern unsigned ivl_stmt_nevent(ivl_statement_t net);
|
||||
extern ivl_event_t ivl_stmt_events(ivl_statement_t net, unsigned idx);
|
||||
@@ -1708,6 +1720,18 @@ _END_DECL
|
||||
|
||||
/*
|
||||
* $Log: ivl_target.h,v $
|
||||
* Revision 1.170 2006/08/08 05:11:37 steve
|
||||
* Handle 64bit delay constants.
|
||||
*
|
||||
* Revision 1.169 2006/07/30 02:51:35 steve
|
||||
* Fix/implement signed right shift.
|
||||
*
|
||||
* Revision 1.168 2006/06/18 04:15:50 steve
|
||||
* Add support for system functions in continuous assignments.
|
||||
*
|
||||
* Revision 1.167 2006/04/16 00:15:43 steve
|
||||
* Fix part selects in l-values.
|
||||
*
|
||||
* Revision 1.166 2006/04/10 00:37:42 steve
|
||||
* Add support for generate loops w/ wires and gates.
|
||||
*
|
||||
|
||||
+85
-34
@@ -17,7 +17,7 @@ const char COPYRIGHT[] =
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: main.c,v 1.20 2004/09/10 00:15:45 steve Exp $"
|
||||
#ident "$Id: main.c,v 1.22 2006/07/26 00:11:40 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -58,6 +58,8 @@ extern int getopt(int argc, char*argv[], const char*fmt);
|
||||
extern int optind;
|
||||
extern const char*optarg;
|
||||
#endif
|
||||
/* Path to the dependency file, if there is one. */
|
||||
char *dep_path = NULL;
|
||||
|
||||
/*
|
||||
* Keep in source_list an array of pointers to file names. The array
|
||||
@@ -89,6 +91,76 @@ int line_direct_flag = 0;
|
||||
unsigned error_count = 0;
|
||||
FILE *depend_file = NULL;
|
||||
|
||||
static int flist_read_flags(const char*path)
|
||||
{
|
||||
char line_buf[2048];
|
||||
FILE*fd = fopen(path, "r");
|
||||
if (fd == 0) {
|
||||
fprintf(stderr, "%s: unable to open for reading.\n", path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (fgets(line_buf, sizeof line_buf, fd) != 0) {
|
||||
/* Skip leading white space. */
|
||||
char*cp = line_buf + strspn(line_buf, " \t\r\b\f");
|
||||
/* Remove trailing white space. */
|
||||
char*tail = cp + strlen(cp);
|
||||
while (tail > cp) {
|
||||
if (! isspace(tail[-1]))
|
||||
break;
|
||||
tail -= 1;
|
||||
tail[0] = 0;
|
||||
}
|
||||
|
||||
/* Skip empty lines */
|
||||
if (*cp == 0)
|
||||
continue;
|
||||
/* Skip comment lines */
|
||||
if (cp[0] == '#')
|
||||
continue;
|
||||
|
||||
/* The arg points to the argument to the keyword. */
|
||||
char*arg = strchr(cp, ':');
|
||||
if (arg) *arg++ = 0;
|
||||
|
||||
if (strcmp(cp,"D") == 0) {
|
||||
char*val = strchr(arg, '=');
|
||||
if (val)
|
||||
*val++ = 0;
|
||||
else
|
||||
val = "1";
|
||||
|
||||
define_macro(arg, val, 0);
|
||||
|
||||
} else if (strcmp(cp,"I") == 0) {
|
||||
include_dir = realloc(include_dir,
|
||||
(include_cnt+1)*sizeof(char*));
|
||||
include_dir[include_cnt] = strdup(arg);
|
||||
include_cnt += 1;
|
||||
|
||||
} else if (strcmp(cp,"keyword") == 0) {
|
||||
char*buf = malloc(strlen(arg) + 2);
|
||||
buf[0] = '`';
|
||||
strcpy(buf+1, optarg);
|
||||
define_macro(optarg, buf, 1);
|
||||
free(buf);
|
||||
|
||||
} else if (strcmp(cp,"M") == 0) {
|
||||
if (dep_path) {
|
||||
fprintf(stderr, "duplicate -M flag.\n");
|
||||
} else {
|
||||
dep_path = arg;
|
||||
}
|
||||
|
||||
} else {
|
||||
fprintf(stderr, "%s: Invalid keyword %s\n", path, cp);
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function reads from a file a list of file names. Each name
|
||||
* starts with the first non-space character, and ends with the last
|
||||
@@ -127,7 +199,6 @@ int main(int argc, char*argv[])
|
||||
const char*flist_path = 0;
|
||||
unsigned flag_errors = 0;
|
||||
char*out_path = 0;
|
||||
char *dep_path = NULL;
|
||||
FILE*out;
|
||||
|
||||
/* Define preprocessor keywords that I plan to just pass. */
|
||||
@@ -153,20 +224,11 @@ int main(int argc, char*argv[])
|
||||
include_dir[0] = strdup(".");
|
||||
include_cnt = 1;
|
||||
|
||||
while ((opt = getopt(argc, argv, "D:f:I:K:LM:o:v")) != EOF) switch (opt) {
|
||||
while ((opt=getopt(argc, argv, "F:f:K:Lo:v")) != EOF) switch (opt) {
|
||||
|
||||
case 'D': {
|
||||
char*tmp = strdup(optarg);
|
||||
char*val = strchr(tmp, '=');
|
||||
if (val)
|
||||
*val++ = 0;
|
||||
else
|
||||
val = "1";
|
||||
|
||||
define_macro(tmp, val, 0);
|
||||
free(tmp);
|
||||
break;
|
||||
}
|
||||
case 'F':
|
||||
flist_read_flags(optarg);
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
if (flist_path) {
|
||||
@@ -176,13 +238,6 @@ int main(int argc, char*argv[])
|
||||
flist_path = optarg;
|
||||
break;
|
||||
|
||||
case 'I':
|
||||
include_dir = realloc(include_dir,
|
||||
(include_cnt+1)*sizeof(char*));
|
||||
include_dir[include_cnt] = strdup(optarg);
|
||||
include_cnt += 1;
|
||||
break;
|
||||
|
||||
case 'K': {
|
||||
char*buf = malloc(strlen(optarg) + 2);
|
||||
buf[0] = '`';
|
||||
@@ -196,14 +251,6 @@ int main(int argc, char*argv[])
|
||||
line_direct_flag = 1;
|
||||
break;
|
||||
|
||||
case 'M':
|
||||
if (dep_path) {
|
||||
fprintf(stderr, "duplicate -M flag.\n");
|
||||
} else {
|
||||
dep_path = optarg;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
if (out_path) {
|
||||
fprintf(stderr, "duplicate -o flag.\n");
|
||||
@@ -225,13 +272,11 @@ int main(int argc, char*argv[])
|
||||
}
|
||||
|
||||
if (flag_errors) {
|
||||
fprintf(stderr, "\nUsage: %s [-v][-L][-I<dir>][-D<def>] <file>...\n"
|
||||
" -D<def> - Predefine a value.\n"
|
||||
fprintf(stderr, "\nUsage: %s [-v][-L][-F<fil>][-f<fil>] <file>...\n"
|
||||
" -F<fil> - Get defines and includes from file\n"
|
||||
" -f<fil> - Read the sources listed in the file\n"
|
||||
" -I<dir> - Add an include file search directory\n"
|
||||
" -K<def> - Define a keyword macro that I just pass\n"
|
||||
" -L - Emit line number directives\n"
|
||||
" -M<fil> - Write dependencies to <fil>\n"
|
||||
" -o<fil> - Send the output to <fil>\n"
|
||||
" -v - Print version information\n",
|
||||
argv[0]);
|
||||
@@ -290,6 +335,12 @@ int main(int argc, char*argv[])
|
||||
|
||||
/*
|
||||
* $Log: main.c,v $
|
||||
* Revision 1.22 2006/07/26 00:11:40 steve
|
||||
* Pass depfiles through temp defines file.
|
||||
*
|
||||
* Revision 1.21 2006/07/26 00:02:48 steve
|
||||
* Pass defines and includes through temp file.
|
||||
*
|
||||
* Revision 1.20 2004/09/10 00:15:45 steve
|
||||
* Remove bad casts.
|
||||
*
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
|
||||
%option never-interactive
|
||||
|
||||
%{
|
||||
/*
|
||||
* Copyright (c) 1998-2000 Stephen Williams ([email protected])
|
||||
@@ -19,7 +21,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: lexor.lex,v 1.90 2006/03/30 05:44:36 steve Exp $"
|
||||
#ident "$Id: lexor.lex,v 1.92 2006/07/31 03:50:17 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -132,6 +134,7 @@ W [ \t\b\f\r]+
|
||||
"<<<" { return K_LS; /* Note: Functionally, <<< is the same as <<. */}
|
||||
">>" { return K_RS; }
|
||||
">>>" { return K_RSS; }
|
||||
"**" { return K_POW; }
|
||||
"<=" { return K_LE; }
|
||||
">=" { return K_GE; }
|
||||
"=>" { return K_EG; }
|
||||
|
||||
@@ -48,6 +48,7 @@ genvar, K_genvar
|
||||
highz0, K_highz0
|
||||
highz1, K_highz1
|
||||
if, K_if
|
||||
ifnone, K_ifnone
|
||||
initial, K_initial
|
||||
inout, K_inout
|
||||
input, K_input
|
||||
|
||||
+23
-9
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: net_design.cc,v 1.48 2005/11/27 05:56:20 steve Exp $"
|
||||
#ident "$Id: net_design.cc,v 1.50 2006/08/08 05:11:37 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -67,8 +67,8 @@ int Design::get_precision() const
|
||||
return des_precision_;
|
||||
}
|
||||
|
||||
unsigned long Design::scale_to_precision(unsigned long val,
|
||||
const NetScope*scope) const
|
||||
uint64_t Design::scale_to_precision(uint64_t val,
|
||||
const NetScope*scope) const
|
||||
{
|
||||
int units = scope->time_unit();
|
||||
assert( units >= des_precision_ );
|
||||
@@ -327,12 +327,20 @@ void NetScope::evaluate_parameters(Design*des)
|
||||
switch (expr->expr_type()) {
|
||||
case IVL_VT_REAL:
|
||||
if (! dynamic_cast<const NetECReal*>(expr)) {
|
||||
cerr << (*cur).second.expr->get_line()
|
||||
<< ": internal error: "
|
||||
"unable to evaluate real parameter values: " <<
|
||||
*expr << endl;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
|
||||
NetExpr*nexpr = expr->eval_tree();
|
||||
if (nexpr == 0) {
|
||||
cerr << (*cur).second.expr->get_line()
|
||||
<< ": internal error: "
|
||||
<< "unable to evaluate real parameter value: "
|
||||
<< *expr << endl;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
assert(nexpr);
|
||||
delete expr;
|
||||
(*cur).second.expr = nexpr;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -554,6 +562,12 @@ void Design::delete_process(NetProcTop*top)
|
||||
|
||||
/*
|
||||
* $Log: net_design.cc,v $
|
||||
* Revision 1.50 2006/08/08 05:11:37 steve
|
||||
* Handle 64bit delay constants.
|
||||
*
|
||||
* Revision 1.49 2006/07/31 03:50:17 steve
|
||||
* Add support for power in constant expressions.
|
||||
*
|
||||
* Revision 1.48 2005/11/27 05:56:20 steve
|
||||
* Handle bit select of parameter with ranges.
|
||||
*
|
||||
|
||||
+38
-1
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: net_expr.cc,v 1.26 2005/11/26 00:35:43 steve Exp $"
|
||||
#ident "$Id: net_expr.cc,v 1.27 2006/07/31 03:50:17 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -248,6 +248,40 @@ ivl_variable_type_t NetEBMult::expr_type() const
|
||||
return IVL_VT_LOGIC;
|
||||
}
|
||||
|
||||
NetEBPow::NetEBPow(char op, NetExpr*l, NetExpr*r)
|
||||
: NetEBinary(op, l, r)
|
||||
{
|
||||
assert(op == 'p');
|
||||
expr_width(l->expr_width());
|
||||
cast_signed(l->has_sign() || r->has_sign());
|
||||
}
|
||||
|
||||
NetEBPow::~NetEBPow()
|
||||
{
|
||||
}
|
||||
|
||||
NetEBPow* NetEBPow::dup_expr() const
|
||||
{
|
||||
NetEBPow*result = new NetEBPow(op_, left_->dup_expr(),
|
||||
right_->dup_expr());
|
||||
result->set_line(*this);
|
||||
return result;
|
||||
}
|
||||
|
||||
ivl_variable_type_t NetEBPow::expr_type() const
|
||||
{
|
||||
if (right_->expr_type() == IVL_VT_REAL)
|
||||
return IVL_VT_REAL;
|
||||
if (left_->expr_type() == IVL_VT_REAL)
|
||||
return IVL_VT_REAL;
|
||||
if (left_->has_sign())
|
||||
return IVL_VT_REAL;
|
||||
if (right_->has_sign())
|
||||
return IVL_VT_REAL;
|
||||
|
||||
return IVL_VT_LOGIC;
|
||||
}
|
||||
|
||||
NetEBShift::NetEBShift(char op, NetExpr*l, NetExpr*r)
|
||||
: NetEBinary(op, l, r)
|
||||
{
|
||||
@@ -526,6 +560,9 @@ ivl_variable_type_t NetESFunc::expr_type() const
|
||||
|
||||
/*
|
||||
* $Log: net_expr.cc,v $
|
||||
* Revision 1.27 2006/07/31 03:50:17 steve
|
||||
* Add support for power in constant expressions.
|
||||
*
|
||||
* Revision 1.26 2005/11/26 00:35:43 steve
|
||||
* More precise about r-value width of constants.
|
||||
*
|
||||
|
||||
+39
-1
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: net_func.cc,v 1.7 2005/03/18 02:56:03 steve Exp $"
|
||||
#ident "$Id: net_func.cc,v 1.8 2006/06/18 04:15:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -112,8 +112,46 @@ bool PECallFunction::check_call_matches_definition_(Design*des, NetScope*dscope)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
NetSysFunc::NetSysFunc(NetScope*s, perm_string n,
|
||||
const struct sfunc_return_type*def,
|
||||
unsigned ports)
|
||||
: NetNode(s, n, ports)
|
||||
{
|
||||
def_ = def;
|
||||
|
||||
pin(0).set_dir(Link::OUTPUT);
|
||||
pin(0).set_name(perm_string::literal("Q"), 0);
|
||||
|
||||
for (unsigned idx = 1 ; idx < pin_count() ; idx += 1) {
|
||||
|
||||
pin(idx).set_dir(Link::INPUT);
|
||||
pin(idx).set_name(perm_string::literal("D"), idx-1);
|
||||
pin(idx).drive0(Link::HIGHZ);
|
||||
pin(idx).drive1(Link::HIGHZ);
|
||||
}
|
||||
}
|
||||
|
||||
NetSysFunc::~NetSysFunc()
|
||||
{
|
||||
}
|
||||
|
||||
const char*NetSysFunc::func_name() const
|
||||
{
|
||||
return def_->name;
|
||||
}
|
||||
|
||||
unsigned NetSysFunc::vector_width() const
|
||||
{
|
||||
return def_->wid;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* $Log: net_func.cc,v $
|
||||
* Revision 1.8 2006/06/18 04:15:50 steve
|
||||
* Add support for system functions in continuous assignments.
|
||||
*
|
||||
* Revision 1.7 2005/03/18 02:56:03 steve
|
||||
* Add support for LPM_UFUNC user defined functions.
|
||||
*
|
||||
|
||||
+17
-5
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: net_nex_input.cc,v 1.14 2005/07/11 16:56:50 steve Exp $"
|
||||
#ident "$Id: net_nex_input.cc,v 1.15 2006/04/16 00:15:43 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -170,10 +170,19 @@ NexusSet* NetEUnary::nex_input()
|
||||
|
||||
NexusSet* NetAssign_::nex_input()
|
||||
{
|
||||
if (bmux_ == 0)
|
||||
return new NexusSet;
|
||||
else
|
||||
return bmux_->nex_input();
|
||||
NexusSet*result = new NexusSet;
|
||||
if (bmux_) {
|
||||
NexusSet*tmp = bmux_->nex_input();
|
||||
result->add(*tmp);
|
||||
delete tmp;
|
||||
}
|
||||
if (base_) {
|
||||
NexusSet*tmp = base_->nex_input();
|
||||
result->add(*tmp);
|
||||
delete tmp;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
NexusSet* NetAssignBase::nex_input()
|
||||
@@ -384,6 +393,9 @@ NexusSet* NetWhile::nex_input()
|
||||
|
||||
/*
|
||||
* $Log: net_nex_input.cc,v $
|
||||
* Revision 1.15 2006/04/16 00:15:43 steve
|
||||
* Fix part selects in l-values.
|
||||
*
|
||||
* Revision 1.14 2005/07/11 16:56:50 steve
|
||||
* Remove NetVariable and ivl_variable_t structures.
|
||||
*
|
||||
|
||||
+6
-3
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: net_proc.cc,v 1.6 2002/08/12 01:34:59 steve Exp $"
|
||||
#ident "$Id: net_proc.cc,v 1.7 2006/08/08 05:11:37 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -131,7 +131,7 @@ NetForever::~NetForever()
|
||||
delete statement_;
|
||||
}
|
||||
|
||||
NetPDelay::NetPDelay(unsigned long d, NetProc*st)
|
||||
NetPDelay::NetPDelay(uint64_t d, NetProc*st)
|
||||
: delay_(d), expr_(0), statement_(st)
|
||||
{
|
||||
}
|
||||
@@ -146,7 +146,7 @@ NetPDelay::~NetPDelay()
|
||||
if (expr_) delete expr_;
|
||||
}
|
||||
|
||||
unsigned long NetPDelay::delay() const
|
||||
uint64_t NetPDelay::delay() const
|
||||
{
|
||||
assert(expr_ == 0);
|
||||
return delay_;
|
||||
@@ -177,6 +177,9 @@ const NetExpr* NetRepeat::expr() const
|
||||
|
||||
/*
|
||||
* $Log: net_proc.cc,v $
|
||||
* Revision 1.7 2006/08/08 05:11:37 steve
|
||||
* Handle 64bit delay constants.
|
||||
*
|
||||
* Revision 1.6 2002/08/12 01:34:59 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: netlist.h,v 1.357 2006/04/10 00:37:42 steve Exp $"
|
||||
#ident "$Id: netlist.h,v 1.360 2006/08/08 05:11:37 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -31,6 +31,7 @@
|
||||
# include <string>
|
||||
# include <map>
|
||||
# include <list>
|
||||
# include <stdint.h>
|
||||
# include "ivl_target.h"
|
||||
# include "verinum.h"
|
||||
# include "verireal.h"
|
||||
@@ -1020,6 +1021,28 @@ class NetUserFunc : public NetNode {
|
||||
NetScope*def_;
|
||||
};
|
||||
|
||||
/*
|
||||
* The number of ports includes the return value, so will always be at
|
||||
* least 1.
|
||||
*/
|
||||
class NetSysFunc : public NetNode {
|
||||
|
||||
public:
|
||||
NetSysFunc(NetScope*s, perm_string n,
|
||||
const struct sfunc_return_type*def,
|
||||
unsigned ports);
|
||||
~NetSysFunc();
|
||||
|
||||
unsigned vector_width() const;
|
||||
const char* func_name() const;
|
||||
|
||||
virtual void dump_node(ostream&, unsigned ind) const;
|
||||
virtual bool emit_node(struct target_t*) const;
|
||||
|
||||
private:
|
||||
const struct sfunc_return_type*def_;
|
||||
};
|
||||
|
||||
/* =========
|
||||
* There are cases where expressions need to be represented. The
|
||||
* NetExpr class is the root of a hierarchy that serves that purpose.
|
||||
@@ -2266,11 +2289,11 @@ class NetFuncDef {
|
||||
class NetPDelay : public NetProc {
|
||||
|
||||
public:
|
||||
NetPDelay(unsigned long d, NetProc*st);
|
||||
NetPDelay(uint64_t d, NetProc*st);
|
||||
NetPDelay(NetExpr* d, NetProc*st);
|
||||
~NetPDelay();
|
||||
|
||||
unsigned long delay() const;
|
||||
uint64_t delay() const;
|
||||
const NetExpr*expr() const;
|
||||
|
||||
virtual NexusSet* nex_input();
|
||||
@@ -2282,7 +2305,7 @@ class NetPDelay : public NetProc {
|
||||
bool emit_proc_recurse(struct target_t*) const;
|
||||
|
||||
private:
|
||||
unsigned long delay_;
|
||||
uint64_t delay_;
|
||||
NetExpr*expr_;
|
||||
NetProc*statement_;
|
||||
};
|
||||
@@ -2537,6 +2560,7 @@ class NetProcTop : public LineInfo, public Attrib {
|
||||
* * -- Arithmetic multiply
|
||||
* / -- Arithmetic divide
|
||||
* % -- Arithmetic modulus
|
||||
* p -- Arithmetic power (**)
|
||||
* & -- Bit-wise AND
|
||||
* | -- Bit-wise OR
|
||||
* < -- Less then
|
||||
@@ -2740,6 +2764,28 @@ class NetEBMult : public NetEBinary {
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
* Support the binary multiplication (*) operator.
|
||||
*/
|
||||
class NetEBPow : public NetEBinary {
|
||||
|
||||
public:
|
||||
NetEBPow(char op, NetExpr*l, NetExpr*r);
|
||||
~NetEBPow();
|
||||
|
||||
virtual ivl_variable_type_t expr_type() const;
|
||||
|
||||
virtual bool set_width(unsigned w, bool last_chance);
|
||||
virtual NetEBPow* dup_expr() const;
|
||||
virtual NetExpr* eval_tree();
|
||||
virtual NetNet* synthesize(Design*);
|
||||
|
||||
private:
|
||||
|
||||
NetExpr* eval_tree_real_();
|
||||
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* The binary logical operators are those that return boolean
|
||||
@@ -3349,7 +3395,7 @@ class Design {
|
||||
|
||||
/* This function takes a delay value and a scope, and returns
|
||||
the delay value scaled to the precision of the design. */
|
||||
unsigned long scale_to_precision(unsigned long, const NetScope*)const;
|
||||
uint64_t scale_to_precision(uint64_t, const NetScope*)const;
|
||||
|
||||
/* Look up a scope. If no starting scope is passed, then the
|
||||
path is taken as an absolute scope name. Otherwise, the
|
||||
@@ -3464,6 +3510,15 @@ extern ostream& operator << (ostream&, NetNet::Type);
|
||||
|
||||
/*
|
||||
* $Log: netlist.h,v $
|
||||
* Revision 1.360 2006/08/08 05:11:37 steve
|
||||
* Handle 64bit delay constants.
|
||||
*
|
||||
* Revision 1.359 2006/07/31 03:50:17 steve
|
||||
* Add support for power in constant expressions.
|
||||
*
|
||||
* Revision 1.358 2006/06/18 04:15:50 steve
|
||||
* Add support for system functions in continuous assignments.
|
||||
*
|
||||
* Revision 1.357 2006/04/10 00:37:42 steve
|
||||
* Add support for generate loops w/ wires and gates.
|
||||
*
|
||||
|
||||
+9
-3
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: netmisc.cc,v 1.11 2005/04/08 04:50:31 steve Exp $"
|
||||
#ident "$Id: netmisc.cc,v 1.12 2006/06/02 04:48:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -123,9 +123,10 @@ NetExpr* make_sub_expr(long val, NetExpr*expr)
|
||||
return res;
|
||||
}
|
||||
|
||||
NetExpr* elab_and_eval(Design*des, NetScope*scope, const PExpr*pe)
|
||||
NetExpr* elab_and_eval(Design*des, NetScope*scope,
|
||||
const PExpr*pe, int expr_wid)
|
||||
{
|
||||
NetExpr*tmp = pe->elaborate_expr(des, scope);
|
||||
NetExpr*tmp = pe->elaborate_expr(des, scope, expr_wid, false);
|
||||
if (tmp == 0)
|
||||
return 0;
|
||||
|
||||
@@ -140,6 +141,11 @@ NetExpr* elab_and_eval(Design*des, NetScope*scope, const PExpr*pe)
|
||||
|
||||
/*
|
||||
* $Log: netmisc.cc,v $
|
||||
* Revision 1.12 2006/06/02 04:48:50 steve
|
||||
* Make elaborate_expr methods aware of the width that the context
|
||||
* requires of it. In the process, fix sizing of the width of unary
|
||||
* minus is context determined sizes.
|
||||
*
|
||||
* Revision 1.11 2005/04/08 04:50:31 steve
|
||||
* Don not give to make_add express an unwanted width.
|
||||
*
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: netmisc.h,v 1.24 2005/11/27 05:56:20 steve Exp $"
|
||||
#ident "$Id: netmisc.h,v 1.25 2006/06/02 04:48:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
@@ -114,10 +114,16 @@ extern unsigned count_lval_width(const class NetAssign_*first);
|
||||
* it can. If the expression cannot be elaborated, return 0.
|
||||
*/
|
||||
class PExpr;
|
||||
extern NetExpr* elab_and_eval(Design*des, NetScope*scope, const PExpr*pe);
|
||||
extern NetExpr* elab_and_eval(Design*des, NetScope*scope,
|
||||
const PExpr*pe, int expr_wid);
|
||||
|
||||
/*
|
||||
* $Log: netmisc.h,v $
|
||||
* Revision 1.25 2006/06/02 04:48:50 steve
|
||||
* Make elaborate_expr methods aware of the width that the context
|
||||
* requires of it. In the process, fix sizing of the width of unary
|
||||
* minus is context determined sizes.
|
||||
*
|
||||
* Revision 1.24 2005/11/27 05:56:20 steve
|
||||
* Handle bit select of parameter with ranges.
|
||||
*
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: parse.y,v 1.213 2006/04/10 00:37:42 steve Exp $"
|
||||
#ident "$Id: parse.y,v 1.219 2006/08/08 05:11:37 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -68,6 +68,22 @@ static struct {
|
||||
*/
|
||||
const static struct str_pair_t pull_strength = { PGate::PULL, PGate::PULL };
|
||||
const static struct str_pair_t str_strength = { PGate::STRONG, PGate::STRONG };
|
||||
|
||||
static list<perm_string>* list_from_identifier(char*id)
|
||||
{
|
||||
list<perm_string>*tmp = new list<perm_string>;
|
||||
tmp->push_back(lex_strings.make(id));
|
||||
delete id;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static list<perm_string>* list_from_identifier(list<perm_string>*tmp, char*id)
|
||||
{
|
||||
tmp->push_back(lex_strings.make(id));
|
||||
delete id;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
%}
|
||||
|
||||
%union {
|
||||
@@ -132,7 +148,7 @@ const static struct str_pair_t str_strength = { PGate::STRONG, PGate::STRONG };
|
||||
%token <number> BASED_NUMBER DEC_NUMBER
|
||||
%token <realtime> REALTIME
|
||||
%token K_LE K_GE K_EG K_EQ K_NE K_CEQ K_CNE K_LS K_RS K_RSS K_SG
|
||||
%token K_PO_POS K_PO_NEG
|
||||
%token K_PO_POS K_PO_NEG K_POW
|
||||
%token K_PSTAR K_STARP
|
||||
%token K_LOR K_LAND K_NAND K_NOR K_NXOR K_TRIGGER
|
||||
%token K_always K_and K_assign K_begin K_bool K_buf K_bufif0 K_bufif1 K_case
|
||||
@@ -140,7 +156,7 @@ const static struct str_pair_t str_strength = { PGate::STRONG, PGate::STRONG };
|
||||
%token K_edge K_else K_end K_endcase K_endfunction K_endgenerate K_endmodule
|
||||
%token K_endprimitive K_endspecify K_endtable K_endtask K_event K_for
|
||||
%token K_force K_forever K_fork K_function K_generate K_genvar
|
||||
%token K_highz0 K_highz1 K_if
|
||||
%token K_highz0 K_highz1 K_if K_ifnone
|
||||
%token K_initial K_inout K_input K_integer K_join K_large K_localparam
|
||||
%token K_logic K_macromodule
|
||||
%token K_medium K_module K_nand K_negedge K_nmos K_nor K_not K_notif0
|
||||
@@ -181,6 +197,7 @@ const static struct str_pair_t str_strength = { PGate::STRONG, PGate::STRONG };
|
||||
%type <mports> list_of_ports module_port_list_opt list_of_port_declarations
|
||||
|
||||
%type <wires> task_item task_item_list task_item_list_opt
|
||||
%type <wires> task_port_item task_port_decl task_port_decl_list
|
||||
%type <wires> function_item function_item_list
|
||||
|
||||
%type <named_pexpr> port_name parameter_value_byname
|
||||
@@ -232,13 +249,13 @@ const static struct str_pair_t str_strength = { PGate::STRONG, PGate::STRONG };
|
||||
%left K_LS K_RS K_RSS
|
||||
%left '+' '-'
|
||||
%left '*' '/' '%'
|
||||
%left K_POW
|
||||
%left UNARY_PREC
|
||||
|
||||
/* to resolve dangling else ambiguity. */
|
||||
%nonassoc less_than_K_else
|
||||
%nonassoc K_else
|
||||
|
||||
|
||||
%%
|
||||
|
||||
/* A degenerate source file can be completely empty. */
|
||||
@@ -776,6 +793,12 @@ expression
|
||||
tmp->set_lineno(@2.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
| expression K_POW expression
|
||||
{ PEBinary*tmp = new PEBinary('p', $1, $3);
|
||||
tmp->set_file(@2.text);
|
||||
tmp->set_lineno(@2.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
| expression '*' expression
|
||||
{ PEBinary*tmp = new PEBinary('*', $1, $3);
|
||||
tmp->set_file(@2.text);
|
||||
@@ -1102,7 +1125,7 @@ function_item
|
||||
re = new PENumber(new verinum(INTEGER_WIDTH-1,
|
||||
INTEGER_WIDTH));
|
||||
(*range_stub)[0] = re;
|
||||
re = new PENumber(new verinum(0UL, INTEGER_WIDTH));
|
||||
re = new PENumber(new verinum((uint64_t)0, INTEGER_WIDTH));
|
||||
(*range_stub)[1] = re;
|
||||
svector<PWire*>*tmp
|
||||
= pform_make_task_ports(NetNet::PINPUT,
|
||||
@@ -1287,6 +1310,7 @@ indexed_identifier
|
||||
}
|
||||
| indexed_identifier '[' expression ']'
|
||||
{ PEIdent*tmp = $1;
|
||||
tmp->sel_ = PEIdent::SEL_NONE;
|
||||
tmp->idx_.push_back($3);
|
||||
$$ = tmp;
|
||||
}
|
||||
@@ -1296,17 +1320,9 @@ indexed_identifier
|
||||
non-hierarchical names separated by ',' characters. */
|
||||
list_of_identifiers
|
||||
: IDENTIFIER
|
||||
{ list<perm_string>*tmp = new list<perm_string>;
|
||||
tmp->push_back(lex_strings.make($1));
|
||||
$$ = tmp;
|
||||
delete[]$1;
|
||||
}
|
||||
{ $$ = list_from_identifier($1); }
|
||||
| list_of_identifiers ',' IDENTIFIER
|
||||
{ list<perm_string>*tmp = $1;
|
||||
tmp->push_back(lex_strings.make($3));
|
||||
$$ = tmp;
|
||||
delete[]$3;
|
||||
}
|
||||
{ $$ = list_from_identifier($1, $3); }
|
||||
;
|
||||
|
||||
|
||||
@@ -1480,6 +1496,7 @@ lpvalue
|
||||
{ PEIdent*tmp = $1;
|
||||
tmp->msb_ = $3;
|
||||
tmp->lsb_ = $5;
|
||||
tmp->sel_ = PEIdent::SEL_PART;
|
||||
$$ = tmp;
|
||||
}
|
||||
| indexed_identifier '[' expression K_PO_POS expression ']'
|
||||
@@ -1774,7 +1791,8 @@ module_item
|
||||
|
||||
| K_task IDENTIFIER ';'
|
||||
{ pform_push_scope($2); }
|
||||
task_item_list_opt statement_opt
|
||||
task_item_list_opt
|
||||
statement_opt
|
||||
K_endtask
|
||||
{ PTask*tmp = new PTask;
|
||||
perm_string tmp2 = lex_strings.make($2);
|
||||
@@ -1787,6 +1805,23 @@ module_item
|
||||
delete $2;
|
||||
}
|
||||
|
||||
| K_task IDENTIFIER
|
||||
{ pform_push_scope($2); }
|
||||
'(' task_port_decl_list ')' ';'
|
||||
task_item_list_opt
|
||||
statement_opt
|
||||
K_endtask
|
||||
{ PTask*tmp = new PTask;
|
||||
perm_string tmp2 = lex_strings.make($2);
|
||||
tmp->set_file(@1.text);
|
||||
tmp->set_lineno(@1.first_line);
|
||||
tmp->set_ports($5);
|
||||
tmp->set_statement($9);
|
||||
pform_set_task(tmp2, tmp);
|
||||
pform_pop_scope();
|
||||
delete $2;
|
||||
}
|
||||
|
||||
/* The function declaration rule matches the function declaration
|
||||
header, then pushes the function scope. This causes the
|
||||
definitions in the func_body to take on the scope of the function
|
||||
@@ -2223,6 +2258,7 @@ port_reference
|
||||
}
|
||||
wtmp->msb_ = $3;
|
||||
wtmp->lsb_ = $5;
|
||||
wtmp->sel_ = PEIdent::SEL_PART;
|
||||
Module::port_t*ptmp = new Module::port_t;
|
||||
ptmp->name = perm_string();
|
||||
ptmp->expr = svector<PEIdent*>(1);
|
||||
@@ -2419,6 +2455,9 @@ specify_item
|
||||
| K_if '(' expression ')' specify_edge_path_decl ';'
|
||||
{
|
||||
}
|
||||
| K_ifnone specify_simple_path_decl ';'
|
||||
{
|
||||
}
|
||||
| K_Shold '(' spec_reference_event ',' spec_reference_event
|
||||
',' delay_value spec_notifier_opt ')' ';'
|
||||
{ delete $7;
|
||||
@@ -3001,14 +3040,16 @@ statement_opt
|
||||
| ';' { $$ = 0; }
|
||||
;
|
||||
|
||||
|
||||
/* Task items are, other then the statement, task port items and
|
||||
other block items. */
|
||||
task_item
|
||||
: block_item_decl
|
||||
{ $$ = new svector<PWire*>(0); }
|
||||
: block_item_decl { $$ = new svector<PWire*>(0); }
|
||||
| task_port_item { $$ = $1; }
|
||||
;
|
||||
|
||||
/* The basic port concept. */
|
||||
task_port_item
|
||||
|
||||
| K_input signed_opt range_opt list_of_identifiers ';'
|
||||
: K_input signed_opt range_opt list_of_identifiers ';'
|
||||
{ svector<PWire*>*tmp
|
||||
= pform_make_task_ports(NetNet::PINPUT,
|
||||
IVL_VT_LOGIC, $2,
|
||||
@@ -3043,7 +3084,7 @@ task_item
|
||||
re = new PENumber(new verinum(INTEGER_WIDTH-1,
|
||||
INTEGER_WIDTH));
|
||||
(*range_stub)[0] = re;
|
||||
re = new PENumber(new verinum(0UL, INTEGER_WIDTH));
|
||||
re = new PENumber(new verinum((uint64_t)0, INTEGER_WIDTH));
|
||||
(*range_stub)[1] = re;
|
||||
svector<PWire*>*tmp
|
||||
= pform_make_task_ports(NetNet::PINPUT,
|
||||
@@ -3059,7 +3100,7 @@ task_item
|
||||
re = new PENumber(new verinum(INTEGER_WIDTH-1,
|
||||
INTEGER_WIDTH));
|
||||
(*range_stub)[0] = re;
|
||||
re = new PENumber(new verinum(0UL, INTEGER_WIDTH));
|
||||
re = new PENumber(new verinum((uint64_t)0, INTEGER_WIDTH));
|
||||
(*range_stub)[1] = re;
|
||||
svector<PWire*>*tmp
|
||||
= pform_make_task_ports(NetNet::POUTPUT,
|
||||
@@ -3075,7 +3116,7 @@ task_item
|
||||
re = new PENumber(new verinum(INTEGER_WIDTH-1,
|
||||
INTEGER_WIDTH));
|
||||
(*range_stub)[0] = re;
|
||||
re = new PENumber(new verinum(0UL, INTEGER_WIDTH));
|
||||
re = new PENumber(new verinum((uint64_t)0, INTEGER_WIDTH));
|
||||
(*range_stub)[1] = re;
|
||||
svector<PWire*>*tmp
|
||||
= pform_make_task_ports(NetNet::PINOUT,
|
||||
@@ -3131,6 +3172,125 @@ task_item_list_opt
|
||||
{ $$ = 0; }
|
||||
;
|
||||
|
||||
task_port_decl
|
||||
|
||||
: K_input signed_opt range_opt IDENTIFIER
|
||||
{ svector<PWire*>*tmp
|
||||
= pform_make_task_ports(NetNet::PINPUT,
|
||||
IVL_VT_LOGIC, $2,
|
||||
$3, list_from_identifier($4),
|
||||
@1.text, @1.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
|
||||
| K_output signed_opt range_opt IDENTIFIER
|
||||
{ svector<PWire*>*tmp
|
||||
= pform_make_task_ports(NetNet::POUTPUT,
|
||||
IVL_VT_LOGIC, $2,
|
||||
$3, list_from_identifier($4),
|
||||
@1.text, @1.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
| K_inout signed_opt range_opt IDENTIFIER
|
||||
{ svector<PWire*>*tmp
|
||||
= pform_make_task_ports(NetNet::PINOUT,
|
||||
IVL_VT_LOGIC, $2,
|
||||
$3, list_from_identifier($4),
|
||||
@1.text, @1.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
|
||||
| K_input K_integer IDENTIFIER
|
||||
{ svector<PExpr*>*range_stub
|
||||
= new svector<PExpr*>(2);
|
||||
PExpr*re;
|
||||
re = new PENumber(new verinum(INTEGER_WIDTH-1,
|
||||
INTEGER_WIDTH));
|
||||
(*range_stub)[0] = re;
|
||||
re = new PENumber(new verinum((uint64_t)0, INTEGER_WIDTH));
|
||||
(*range_stub)[1] = re;
|
||||
svector<PWire*>*tmp
|
||||
= pform_make_task_ports(NetNet::PINPUT,
|
||||
IVL_VT_LOGIC, true,
|
||||
range_stub,
|
||||
list_from_identifier($3),
|
||||
@1.text, @1.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
| K_output K_integer IDENTIFIER
|
||||
{ svector<PExpr*>*range_stub
|
||||
= new svector<PExpr*>(2);
|
||||
PExpr*re;
|
||||
re = new PENumber(new verinum(INTEGER_WIDTH-1,
|
||||
INTEGER_WIDTH));
|
||||
(*range_stub)[0] = re;
|
||||
re = new PENumber(new verinum((uint64_t)0, INTEGER_WIDTH));
|
||||
(*range_stub)[1] = re;
|
||||
svector<PWire*>*tmp
|
||||
= pform_make_task_ports(NetNet::POUTPUT,
|
||||
IVL_VT_LOGIC, true,
|
||||
range_stub,
|
||||
list_from_identifier($3),
|
||||
@1.text, @1.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
| K_inout K_integer IDENTIFIER
|
||||
{ svector<PExpr*>*range_stub
|
||||
= new svector<PExpr*>(2);
|
||||
PExpr*re;
|
||||
re = new PENumber(new verinum(INTEGER_WIDTH-1,
|
||||
INTEGER_WIDTH));
|
||||
(*range_stub)[0] = re;
|
||||
re = new PENumber(new verinum((uint64_t)0, INTEGER_WIDTH));
|
||||
(*range_stub)[1] = re;
|
||||
svector<PWire*>*tmp
|
||||
= pform_make_task_ports(NetNet::PINOUT,
|
||||
IVL_VT_LOGIC, true,
|
||||
range_stub,
|
||||
list_from_identifier($3),
|
||||
@1.text, @1.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
|
||||
/* Ports can be real. */
|
||||
|
||||
| K_input K_real IDENTIFIER
|
||||
{ svector<PWire*>*tmp
|
||||
= pform_make_task_ports(NetNet::PINPUT,
|
||||
IVL_VT_REAL, false,
|
||||
0, list_from_identifier($3),
|
||||
@1.text, @1.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
| K_output K_real IDENTIFIER
|
||||
{ svector<PWire*>*tmp
|
||||
= pform_make_task_ports(NetNet::POUTPUT,
|
||||
IVL_VT_REAL, false,
|
||||
0, list_from_identifier($3),
|
||||
@1.text, @1.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
| K_inout K_real IDENTIFIER
|
||||
{ svector<PWire*>*tmp
|
||||
= pform_make_task_ports(NetNet::PINOUT,
|
||||
IVL_VT_REAL, false,
|
||||
0, list_from_identifier($3),
|
||||
@1.text, @1.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
;
|
||||
|
||||
task_port_decl_list
|
||||
: task_port_decl_list ',' task_port_decl
|
||||
{ svector<PWire*>*tmp = new svector<PWire*>(*$1, *$3);
|
||||
delete $1;
|
||||
delete $3;
|
||||
$$ = tmp;
|
||||
}
|
||||
| task_port_decl
|
||||
{ $$ = $1; }
|
||||
;
|
||||
|
||||
udp_body
|
||||
: K_table { lex_start_table(); }
|
||||
udp_entry_list
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: pform.cc,v 1.135 2006/04/10 00:37:42 steve Exp $"
|
||||
#ident "$Id: pform.cc,v 1.136 2006/08/08 05:11:37 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -1583,7 +1583,7 @@ static void pform_set_reg_integer(const char*nm)
|
||||
assert(cur);
|
||||
|
||||
cur->set_range(new PENumber(new verinum(INTEGER_WIDTH-1, INTEGER_WIDTH)),
|
||||
new PENumber(new verinum(0UL, INTEGER_WIDTH)));
|
||||
new PENumber(new verinum((uint64_t)0, INTEGER_WIDTH)));
|
||||
cur->set_signed(true);
|
||||
}
|
||||
|
||||
@@ -1614,7 +1614,7 @@ static void pform_set_reg_time(const char*nm)
|
||||
assert(cur);
|
||||
|
||||
cur->set_range(new PENumber(new verinum(TIME_WIDTH-1, INTEGER_WIDTH)),
|
||||
new PENumber(new verinum(0UL, INTEGER_WIDTH)));
|
||||
new PENumber(new verinum((uint64_t)0, INTEGER_WIDTH)));
|
||||
}
|
||||
|
||||
void pform_set_reg_time(list<perm_string>*names)
|
||||
@@ -1707,6 +1707,9 @@ int pform_parse(const char*path, FILE*file)
|
||||
|
||||
/*
|
||||
* $Log: pform.cc,v $
|
||||
* Revision 1.136 2006/08/08 05:11:37 steve
|
||||
* Handle 64bit delay constants.
|
||||
*
|
||||
* Revision 1.135 2006/04/10 00:37:42 steve
|
||||
* Add support for generate loops w/ wires and gates.
|
||||
*
|
||||
|
||||
+9
-1
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: pform_dump.cc,v 1.92 2006/04/10 00:37:42 steve Exp $"
|
||||
#ident "$Id: pform_dump.cc,v 1.93 2006/04/28 04:19:31 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -162,6 +162,11 @@ void PEIdent::dump(ostream&out) const
|
||||
}
|
||||
out << "]";
|
||||
}
|
||||
|
||||
typedef std::vector<PExpr*>::const_iterator vector_it_t;
|
||||
for (vector_it_t cur = idx_.begin() ; cur != idx_.end() ; cur++) {
|
||||
out << "[" << *(*cur) << "]";
|
||||
}
|
||||
}
|
||||
|
||||
void PEString::dump(ostream&out) const
|
||||
@@ -967,6 +972,9 @@ void PUdp::dump(ostream&out) const
|
||||
|
||||
/*
|
||||
* $Log: pform_dump.cc,v $
|
||||
* Revision 1.93 2006/04/28 04:19:31 steve
|
||||
* Dump indexes of ident expressions
|
||||
*
|
||||
* Revision 1.92 2006/04/10 00:37:42 steve
|
||||
* Add support for generate loops w/ wires and gates.
|
||||
*
|
||||
|
||||
+26
-4
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: set_width.cc,v 1.37 2005/11/26 00:35:44 steve Exp $"
|
||||
#ident "$Id: set_width.cc,v 1.39 2006/07/31 03:50:17 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -185,6 +185,12 @@ bool NetEBMult::set_width(unsigned w, bool)
|
||||
return w == expr_width();
|
||||
}
|
||||
|
||||
bool NetEBPow::set_width(unsigned w, bool last_chance)
|
||||
{
|
||||
bool flag = left_->set_width(w, last_chance);
|
||||
return flag;
|
||||
}
|
||||
|
||||
/*
|
||||
* The shift operator allows the shift amount to have its own
|
||||
* natural width. The width of the operator result is the width of the
|
||||
@@ -373,11 +379,21 @@ bool NetESignal::set_width(unsigned w, bool)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetETernary::set_width(unsigned w, bool)
|
||||
bool NetETernary::set_width(unsigned w, bool last_chance)
|
||||
{
|
||||
bool flag = true;
|
||||
flag = flag && true_val_->set_width(w);
|
||||
flag = flag && false_val_->set_width(w);
|
||||
flag = flag && true_val_->set_width(w, last_chance);
|
||||
flag = flag && false_val_->set_width(w, last_chance);
|
||||
|
||||
/* The ternary really insists that the true and false clauses
|
||||
have the same width. Even if we fail to make the width that
|
||||
the user requests, at least pad the smaller width to suit
|
||||
the larger. */
|
||||
if (true_val_->expr_width() < false_val_->expr_width())
|
||||
true_val_ = pad_to_width(true_val_, false_val_->expr_width());
|
||||
if (false_val_->expr_width() < true_val_->expr_width())
|
||||
false_val_ = pad_to_width(false_val_, true_val_->expr_width());
|
||||
|
||||
expr_width(true_val_->expr_width());
|
||||
return flag;
|
||||
}
|
||||
@@ -424,6 +440,12 @@ bool NetEUReduce::set_width(unsigned w, bool)
|
||||
|
||||
/*
|
||||
* $Log: set_width.cc,v $
|
||||
* Revision 1.39 2006/07/31 03:50:17 steve
|
||||
* Add support for power in constant expressions.
|
||||
*
|
||||
* Revision 1.38 2006/05/02 04:29:42 steve
|
||||
* Be more stubborn about widths.
|
||||
*
|
||||
* Revision 1.37 2005/11/26 00:35:44 steve
|
||||
* More precise about r-value width of constants.
|
||||
*
|
||||
|
||||
+28
-46
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: t-dll-api.cc,v 1.133 2006/02/02 02:43:59 steve Exp $"
|
||||
#ident "$Id: t-dll-api.cc,v 1.135 2006/08/08 05:11:37 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -852,6 +852,11 @@ extern "C" ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx)
|
||||
assert(idx == 0);
|
||||
return net->u_.repeat.a;
|
||||
|
||||
case IVL_LPM_SFUNC:
|
||||
// Skip the return port.
|
||||
assert(idx < (net->u_.sfunc.ports-1));
|
||||
return net->u_.sfunc.pins[idx+1];
|
||||
|
||||
case IVL_LPM_UFUNC:
|
||||
// Skip the return port.
|
||||
assert(idx < (net->u_.ufunc.ports-1));
|
||||
@@ -1005,6 +1010,10 @@ extern "C" ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx)
|
||||
assert(idx == 0);
|
||||
return net->u_.shift.q;
|
||||
|
||||
case IVL_LPM_SFUNC:
|
||||
assert(idx == 0);
|
||||
return net->u_.sfunc.pins[0];
|
||||
|
||||
case IVL_LPM_UFUNC:
|
||||
assert(idx == 0);
|
||||
return net->u_.ufunc.pins[0];
|
||||
@@ -1096,6 +1105,8 @@ extern "C" int ivl_lpm_signed(ivl_lpm_t net)
|
||||
return net->u_.shift.signed_flag;
|
||||
case IVL_LPM_SIGN_EXT: // Sign extend is always signed.
|
||||
return 1;
|
||||
case IVL_LPM_SFUNC:
|
||||
return 0;
|
||||
case IVL_LPM_UFUNC:
|
||||
return 0;
|
||||
case IVL_LPM_CONCAT: // Concatenations are always unsigned
|
||||
@@ -1117,6 +1128,8 @@ extern "C" unsigned ivl_lpm_size(ivl_lpm_t net)
|
||||
switch (net->type) {
|
||||
case IVL_LPM_MUX:
|
||||
return net->u_.mux.size;
|
||||
case IVL_LPM_SFUNC:
|
||||
return net->u_.sfunc.ports - 1;
|
||||
case IVL_LPM_UFUNC:
|
||||
return net->u_.ufunc.ports - 1;
|
||||
case IVL_LPM_REPEAT:
|
||||
@@ -1127,6 +1140,12 @@ extern "C" unsigned ivl_lpm_size(ivl_lpm_t net)
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" const char* ivl_lpm_string(ivl_lpm_t net)
|
||||
{
|
||||
assert(net->type == IVL_LPM_SFUNC);
|
||||
return net->u_.sfunc.fun_name;
|
||||
}
|
||||
|
||||
extern "C" ivl_lpm_type_t ivl_lpm_type(ivl_lpm_t net)
|
||||
{
|
||||
return net->type;
|
||||
@@ -1135,50 +1154,7 @@ extern "C" ivl_lpm_type_t ivl_lpm_type(ivl_lpm_t net)
|
||||
extern "C" unsigned ivl_lpm_width(ivl_lpm_t net)
|
||||
{
|
||||
assert(net);
|
||||
switch (net->type) {
|
||||
case IVL_LPM_FF:
|
||||
case IVL_LPM_RAM:
|
||||
return net->u_.ff.width;
|
||||
case IVL_LPM_MUX:
|
||||
return net->u_.mux.width;
|
||||
case IVL_LPM_ADD:
|
||||
case IVL_LPM_CMP_EEQ:
|
||||
case IVL_LPM_CMP_EQ:
|
||||
case IVL_LPM_CMP_GE:
|
||||
case IVL_LPM_CMP_GT:
|
||||
case IVL_LPM_CMP_NE:
|
||||
case IVL_LPM_CMP_NEE:
|
||||
case IVL_LPM_DIVIDE:
|
||||
case IVL_LPM_MOD:
|
||||
case IVL_LPM_MULT:
|
||||
case IVL_LPM_SUB:
|
||||
return net->u_.arith.width;
|
||||
case IVL_LPM_RE_AND:
|
||||
case IVL_LPM_RE_OR:
|
||||
case IVL_LPM_RE_XOR:
|
||||
case IVL_LPM_RE_NAND:
|
||||
case IVL_LPM_RE_NOR:
|
||||
case IVL_LPM_RE_XNOR:
|
||||
case IVL_LPM_SIGN_EXT:
|
||||
return net->u_.reduce.width;
|
||||
case IVL_LPM_SHIFTL:
|
||||
case IVL_LPM_SHIFTR:
|
||||
return net->u_.shift.width;
|
||||
case IVL_LPM_UFUNC:
|
||||
return net->u_.ufunc.width;
|
||||
case IVL_LPM_CONCAT:
|
||||
return net->u_.concat.width;
|
||||
case IVL_LPM_PART_VP:
|
||||
case IVL_LPM_PART_PV:
|
||||
return net->u_.part.width;
|
||||
case IVL_LPM_PART_BI:
|
||||
return net->u_.part.width;
|
||||
case IVL_LPM_REPEAT:
|
||||
return net->u_.repeat.width;
|
||||
default:
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
return net->width;
|
||||
}
|
||||
|
||||
extern "C" ivl_memory_t ivl_lpm_memory(ivl_lpm_t net)
|
||||
@@ -1848,7 +1824,7 @@ extern "C" ivl_expr_t ivl_stmt_delay_expr(ivl_statement_t net)
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" unsigned long ivl_stmt_delay_val(ivl_statement_t net)
|
||||
extern "C" uint64_t ivl_stmt_delay_val(ivl_statement_t net)
|
||||
{
|
||||
assert(net->type_ == IVL_ST_DELAY);
|
||||
return net->u_.delay_.delay_;
|
||||
@@ -2033,6 +2009,12 @@ extern "C" ivl_statement_t ivl_stmt_sub_stmt(ivl_statement_t net)
|
||||
|
||||
/*
|
||||
* $Log: t-dll-api.cc,v $
|
||||
* Revision 1.135 2006/08/08 05:11:37 steve
|
||||
* Handle 64bit delay constants.
|
||||
*
|
||||
* Revision 1.134 2006/06/18 04:15:50 steve
|
||||
* Add support for system functions in continuous assignments.
|
||||
*
|
||||
* Revision 1.133 2006/02/02 02:43:59 steve
|
||||
* Allow part selects of memory words in l-values.
|
||||
*
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: t-dll.cc,v 1.156 2006/04/10 00:37:42 steve Exp $"
|
||||
#ident "$Id: t-dll.cc,v 1.157 2006/06/18 04:15:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -904,7 +904,7 @@ bool dll_target::sign_extend(const NetSignExtend*net)
|
||||
{
|
||||
struct ivl_lpm_s*obj = new struct ivl_lpm_s;
|
||||
obj->type = IVL_LPM_SIGN_EXT;
|
||||
obj->u_.reduce.width = net->width();
|
||||
obj->width = net->width();
|
||||
obj->name = net->name();
|
||||
obj->scope = find_scope(des_, net->scope());
|
||||
assert(obj->scope);
|
||||
@@ -959,7 +959,7 @@ bool dll_target::ureduce(const NetUReduce*net)
|
||||
obj->scope = find_scope(des_, net->scope());
|
||||
assert(obj->scope);
|
||||
|
||||
obj->u_.reduce.width = net->width();
|
||||
obj->width = net->width();
|
||||
|
||||
const Nexus*nex;
|
||||
|
||||
@@ -988,7 +988,7 @@ void dll_target::net_case_cmp(const NetCaseCmp*net)
|
||||
obj->scope = find_scope(des_, net->scope());
|
||||
assert(obj->scope);
|
||||
|
||||
obj->u_.arith.width = net->width();
|
||||
obj->width = net->width();
|
||||
obj->u_.arith.signed_flag = 0;
|
||||
|
||||
const Nexus*nex;
|
||||
@@ -1014,6 +1014,46 @@ void dll_target::net_case_cmp(const NetCaseCmp*net)
|
||||
scope_add_lpm(obj->scope, obj);
|
||||
}
|
||||
|
||||
bool dll_target::net_sysfunction(const NetSysFunc*net)
|
||||
{
|
||||
unsigned idx;
|
||||
const Nexus*nex;
|
||||
|
||||
struct ivl_lpm_s*obj = new struct ivl_lpm_s;
|
||||
obj->type = IVL_LPM_SFUNC;
|
||||
obj->name = net->name();
|
||||
obj->scope = find_scope(des_, net->scope());
|
||||
assert(obj->scope);
|
||||
|
||||
obj->u_.sfunc.ports = net->pin_count();
|
||||
|
||||
assert(net->pin_count() >= 1);
|
||||
obj->width = net->vector_width();
|
||||
|
||||
obj->u_.sfunc.fun_name = net->func_name();
|
||||
|
||||
obj->u_.sfunc.pins = new ivl_nexus_t[net->pin_count()];
|
||||
|
||||
nex = net->pin(0).nexus();
|
||||
assert(nex->t_cookie());
|
||||
|
||||
obj->u_.sfunc.pins[0] = (ivl_nexus_t) nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.sfunc.pins[0], obj, 0,
|
||||
IVL_DR_STRONG, IVL_DR_STRONG);
|
||||
|
||||
for (idx = 1 ; idx < net->pin_count() ; idx += 1) {
|
||||
nex = net->pin(idx).nexus();
|
||||
assert(nex->t_cookie());
|
||||
|
||||
obj->u_.sfunc.pins[idx] = (ivl_nexus_t) nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.sfunc.pins[idx], obj, 0,
|
||||
IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
}
|
||||
|
||||
scope_add_lpm(obj->scope, obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* An IVL_LPM_UFUNC represents a node in a combinational expression
|
||||
* that calls a user defined function. I create an LPM object that has
|
||||
@@ -1039,7 +1079,7 @@ bool dll_target::net_function(const NetUserFunc*net)
|
||||
obj->u_.ufunc.ports = net->pin_count();
|
||||
|
||||
assert(net->pin_count() >= 1);
|
||||
obj->u_.ufunc.width = net->port_width(0);
|
||||
obj->width = net->port_width(0);
|
||||
|
||||
/* Now collect all the pins and connect them to the nexa of
|
||||
the net. The output pins have strong drive, and the
|
||||
@@ -1177,9 +1217,9 @@ void dll_target::lpm_add_sub(const NetAddSub*net)
|
||||
/* Choose the width of the adder. If the carry bit is
|
||||
connected, then widen the adder by one and plan on leaving
|
||||
the fake inputs unconnected. */
|
||||
obj->u_.arith.width = net->width();
|
||||
obj->width = net->width();
|
||||
if (net->pin_Cout().is_linked()) {
|
||||
obj->u_.arith.width += 1;
|
||||
obj->width += 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -1235,7 +1275,7 @@ void dll_target::lpm_clshift(const NetCLShift*net)
|
||||
else
|
||||
obj->u_.shift.signed_flag = 0;
|
||||
|
||||
obj->u_.shift.width = net->width();
|
||||
obj->width = net->width();
|
||||
obj->u_.shift.select = net->width_dist();
|
||||
|
||||
const Nexus*nex;
|
||||
@@ -1276,7 +1316,7 @@ void dll_target::lpm_compare(const NetCompare*net)
|
||||
|
||||
bool swap_operands = false;
|
||||
|
||||
obj->u_.arith.width = net->width();
|
||||
obj->width = net->width();
|
||||
obj->u_.arith.signed_flag = net->get_signed()? 1 : 0;
|
||||
|
||||
const Nexus*nex;
|
||||
@@ -1377,7 +1417,7 @@ void dll_target::lpm_divide(const NetDivide*net)
|
||||
|
||||
unsigned wid = net->width_r();
|
||||
|
||||
obj->u_.arith.width = wid;
|
||||
obj->width = wid;
|
||||
obj->u_.arith.signed_flag = net->get_signed()? 1 : 0;
|
||||
|
||||
const Nexus*nex;
|
||||
@@ -1415,7 +1455,7 @@ void dll_target::lpm_modulo(const NetModulo*net)
|
||||
|
||||
unsigned wid = net->width_r();
|
||||
|
||||
obj->u_.arith.width = wid;
|
||||
obj->width = wid;
|
||||
obj->u_.arith.signed_flag = 0;
|
||||
|
||||
const Nexus*nex;
|
||||
@@ -1449,7 +1489,7 @@ void dll_target::lpm_ff(const NetFF*net)
|
||||
obj->scope = find_scope(des_, net->scope());
|
||||
assert(obj->scope);
|
||||
|
||||
obj->u_.ff.width = net->width();
|
||||
obj->width = net->width();
|
||||
|
||||
scope_add_lpm(obj->scope, obj);
|
||||
|
||||
@@ -1548,7 +1588,7 @@ void dll_target::lpm_ram_dq(const NetRamDq*net)
|
||||
obj->scope = find_scope(des_, net->mem()->scope());
|
||||
assert(obj->scope);
|
||||
|
||||
obj->u_.ff.width = net->width();
|
||||
obj->width = net->width();
|
||||
obj->u_.ff.swid = net->awidth();
|
||||
|
||||
scope_add_lpm(obj->scope, obj);
|
||||
@@ -1619,7 +1659,7 @@ void dll_target::lpm_mult(const NetMult*net)
|
||||
|
||||
unsigned wid = net->width_r();
|
||||
|
||||
obj->u_.arith.width = wid;
|
||||
obj->width = wid;
|
||||
|
||||
const Nexus*nex;
|
||||
|
||||
@@ -1657,7 +1697,7 @@ void dll_target::lpm_mux(const NetMux*net)
|
||||
obj->scope = find_scope(des_, net->scope());
|
||||
assert(obj->scope);
|
||||
|
||||
obj->u_.mux.width = net->width();
|
||||
obj->width = net->width();
|
||||
obj->u_.mux.size = net->size();
|
||||
obj->u_.mux.swid = net->sel_width();
|
||||
|
||||
@@ -1701,7 +1741,7 @@ bool dll_target::concat(const NetConcat*net)
|
||||
obj->scope = find_scope(des_, net->scope());
|
||||
assert(obj->scope);
|
||||
|
||||
obj->u_.concat.width = net->width();
|
||||
obj->width = net->width();
|
||||
|
||||
obj->u_.concat.inputs = net->pin_count() - 1;
|
||||
obj->u_.concat.pins = new ivl_nexus_t[obj->u_.concat.inputs+1];
|
||||
@@ -1743,7 +1783,7 @@ bool dll_target::part_select(const NetPartSelect*net)
|
||||
obj->u_.part.signed_flag = 0;
|
||||
|
||||
/* Choose the width of the part select. */
|
||||
obj->u_.part.width = net->width();
|
||||
obj->width = net->width();
|
||||
obj->u_.part.base = net->base();
|
||||
obj->u_.part.s = 0;
|
||||
|
||||
@@ -1834,7 +1874,7 @@ bool dll_target::replicate(const NetReplicate*net)
|
||||
obj->scope = find_scope(des_, net->scope());
|
||||
assert(obj->scope);
|
||||
|
||||
obj->u_.repeat.width = net->width();
|
||||
obj->width = net->width();
|
||||
obj->u_.repeat.count = net->repeat();
|
||||
|
||||
ivl_drive_t dr = IVL_DR_STRONG;
|
||||
@@ -2167,6 +2207,9 @@ extern const struct target tgt_dll = { "dll", &dll_target_obj };
|
||||
|
||||
/*
|
||||
* $Log: t-dll.cc,v $
|
||||
* Revision 1.157 2006/06/18 04:15:50 steve
|
||||
* Add support for system functions in continuous assignments.
|
||||
*
|
||||
* Revision 1.156 2006/04/10 00:37:42 steve
|
||||
* Add support for generate loops w/ wires and gates.
|
||||
*
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: t-dll.h,v 1.130 2006/02/02 02:43:59 steve Exp $"
|
||||
#ident "$Id: t-dll.h,v 1.132 2006/08/08 05:11:37 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "target.h"
|
||||
@@ -86,6 +86,7 @@ struct dll_target : public target_t, public expr_scan_t {
|
||||
bool part_select(const NetPartSelect*);
|
||||
bool replicate(const NetReplicate*);
|
||||
void net_assign(const NetAssign_*);
|
||||
bool net_sysfunction(const NetSysFunc*);
|
||||
bool net_function(const NetUserFunc*);
|
||||
bool net_const(const NetConst*);
|
||||
bool net_literal(const NetLiteral*);
|
||||
@@ -282,10 +283,11 @@ struct ivl_lpm_s {
|
||||
ivl_lpm_type_t type;
|
||||
ivl_scope_t scope;
|
||||
perm_string name;
|
||||
// Value returned by ivl_lpm_width;
|
||||
unsigned width;
|
||||
|
||||
union {
|
||||
struct ivl_lpm_ff_s {
|
||||
unsigned width;
|
||||
unsigned swid; // ram only
|
||||
ivl_nexus_t clk;
|
||||
ivl_nexus_t we;
|
||||
@@ -311,7 +313,6 @@ struct ivl_lpm_s {
|
||||
} ff;
|
||||
|
||||
struct ivl_lpm_mux_s {
|
||||
unsigned width;
|
||||
unsigned size;
|
||||
unsigned swid;
|
||||
ivl_nexus_t*d;
|
||||
@@ -319,26 +320,22 @@ struct ivl_lpm_s {
|
||||
} mux;
|
||||
|
||||
struct ivl_lpm_shift_s {
|
||||
unsigned width;
|
||||
unsigned select;
|
||||
unsigned signed_flag :1;
|
||||
ivl_nexus_t q, d, s;
|
||||
} shift;
|
||||
|
||||
struct ivl_lpm_arith_s {
|
||||
unsigned width;
|
||||
unsigned signed_flag :1;
|
||||
ivl_nexus_t q, a, b;
|
||||
} arith;
|
||||
|
||||
struct ivl_concat_s {
|
||||
unsigned width;
|
||||
unsigned inputs;
|
||||
ivl_nexus_t*pins;
|
||||
} concat;
|
||||
|
||||
struct ivl_part_s {
|
||||
unsigned width;
|
||||
unsigned base;
|
||||
unsigned signed_flag :1;
|
||||
ivl_nexus_t q, a, s;
|
||||
@@ -346,20 +343,23 @@ struct ivl_lpm_s {
|
||||
|
||||
// IVL_LPM_RE_* and IVL_LPM_SIGN_EXT use this.
|
||||
struct ivl_lpm_reduce_s {
|
||||
unsigned width;
|
||||
ivl_nexus_t q, a;
|
||||
} reduce;
|
||||
|
||||
struct ivl_lpm_repeat_s {
|
||||
unsigned width;
|
||||
unsigned count;
|
||||
ivl_nexus_t q, a;
|
||||
} repeat;
|
||||
|
||||
struct ivl_lpm_sfunc_s {
|
||||
const char* fun_name;
|
||||
unsigned ports;
|
||||
ivl_nexus_t*pins;
|
||||
} sfunc;
|
||||
|
||||
struct ivl_lpm_ufunc_s {
|
||||
ivl_scope_t def;
|
||||
unsigned ports;
|
||||
unsigned width;
|
||||
ivl_nexus_t*pins;
|
||||
} ufunc;
|
||||
} u_;
|
||||
@@ -626,7 +626,7 @@ struct ivl_statement_s {
|
||||
} condit_;
|
||||
|
||||
struct { /* IVL_ST_DELAY */
|
||||
unsigned long delay_;
|
||||
uint64_t delay_;
|
||||
ivl_statement_t stmt_;
|
||||
} delay_;
|
||||
|
||||
@@ -671,6 +671,12 @@ struct ivl_statement_s {
|
||||
|
||||
/*
|
||||
* $Log: t-dll.h,v $
|
||||
* Revision 1.132 2006/08/08 05:11:37 steve
|
||||
* Handle 64bit delay constants.
|
||||
*
|
||||
* Revision 1.131 2006/06/18 04:15:50 steve
|
||||
* Add support for system functions in continuous assignments.
|
||||
*
|
||||
* Revision 1.130 2006/02/02 02:43:59 steve
|
||||
* Allow part selects of memory words in l-values.
|
||||
*
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: target.cc,v 1.77 2005/07/11 16:56:51 steve Exp $"
|
||||
#ident "$Id: target.cc,v 1.78 2006/06/18 04:15:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -174,6 +174,13 @@ bool target_t::net_const(const NetConst*)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool target_t::net_sysfunction(const NetSysFunc*net)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
"Unhandled NetSysFunc node." << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool target_t::net_function(const NetUserFunc*net)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
@@ -431,6 +438,9 @@ void expr_scan_t::expr_binary(const NetEBinary*ex)
|
||||
|
||||
/*
|
||||
* $Log: target.cc,v $
|
||||
* Revision 1.78 2006/06/18 04:15:50 steve
|
||||
* Add support for system functions in continuous assignments.
|
||||
*
|
||||
* Revision 1.77 2005/07/11 16:56:51 steve
|
||||
* Remove NetVariable and ivl_variable_t structures.
|
||||
*
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: target.h,v 1.74 2005/07/11 16:56:51 steve Exp $"
|
||||
#ident "$Id: target.h,v 1.75 2006/06/18 04:15:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
@@ -94,6 +94,7 @@ struct target_t {
|
||||
virtual void udp(const NetUDP*);
|
||||
virtual void net_case_cmp(const NetCaseCmp*);
|
||||
virtual bool net_const(const NetConst*);
|
||||
virtual bool net_sysfunction(const NetSysFunc*);
|
||||
virtual bool net_function(const NetUserFunc*);
|
||||
virtual bool net_literal(const NetLiteral*);
|
||||
virtual void net_probe(const NetEvProbe*);
|
||||
@@ -170,6 +171,9 @@ extern const struct target *target_table[];
|
||||
|
||||
/*
|
||||
* $Log: target.h,v $
|
||||
* Revision 1.75 2006/06/18 04:15:50 steve
|
||||
* Add support for system functions in continuous assignments.
|
||||
*
|
||||
* Revision 1.74 2005/07/11 16:56:51 steve
|
||||
* Remove NetVariable and ivl_variable_t structures.
|
||||
*
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
*.cache
|
||||
stub.tgt
|
||||
configure
|
||||
config.log
|
||||
config.status
|
||||
Makefile
|
||||
dep
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.15 2005/03/03 04:34:42 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.16 2006/05/01 18:48:24 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
@@ -73,17 +73,24 @@ distclean: clean
|
||||
rm -f Makefile
|
||||
|
||||
install: all installdirs $(libdir)/ivl/stub.tgt \
|
||||
$(includedir)/vpi_user.h
|
||||
$(libdir)/ivl/stub.conf $(libdir)/ivl/stub-s.conf
|
||||
|
||||
$(libdir)/ivl/stub.tgt: ./stub.tgt
|
||||
$(INSTALL_PROGRAM) ./stub.tgt $(libdir)/ivl/stub.tgt
|
||||
|
||||
$(libdir)/ivl/stub.conf: ./stub.conf
|
||||
$(INSTALL_DATA) ./stub.conf $(libdir)/ivl/stub.conf
|
||||
|
||||
$(libdir)/ivl/stub-s.conf: ./stub-s.conf
|
||||
$(INSTALL_DATA) ./stub-s.conf $(libdir)/ivl/stub-s.conf
|
||||
|
||||
installdirs: ../mkinstalldirs
|
||||
$(srcdir)/../mkinstalldirs $(includedir) $(bindir) $(libdir)/ivl
|
||||
|
||||
uninstall:
|
||||
rm -f $(libdir)/ivl/stub.tgt
|
||||
rm -f $(libdir)/ivl/stub.conf
|
||||
rm -f $(libdir)/ivl/stub-s.conf
|
||||
|
||||
|
||||
-include $(patsubst %.o, dep/%.d, $O)
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
dnl Process this file with autoconf to produce a configure script.
|
||||
AC_INIT(stub.c)
|
||||
|
||||
dnl Checks for programs.
|
||||
AC_PROG_CC
|
||||
|
||||
AC_PROG_INSTALL
|
||||
|
||||
AC_CANONICAL_HOST
|
||||
# $host
|
||||
|
||||
# Combined check for Microsoft-related bogosities; sets WIN32 if found
|
||||
AX_WIN32
|
||||
|
||||
# may modify CPPFLAGS and CFLAGS
|
||||
AX_CPP_PRECOMP
|
||||
|
||||
# Compiler option for position independent code, needed whan making shared objects.
|
||||
AX_C_PICFLAG
|
||||
|
||||
# linker options when building a shared library
|
||||
AX_LD_SHAREDLIB_OPTS
|
||||
|
||||
AX_CPP_IDENT
|
||||
|
||||
AC_OUTPUT(Makefile)
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: statement.c,v 1.9 2006/02/02 02:43:59 steve Exp $"
|
||||
#ident "$Id: statement.c,v 1.10 2006/08/08 05:11:37 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -301,7 +301,7 @@ void show_statement(ivl_statement_t net, unsigned ind)
|
||||
break;
|
||||
|
||||
case IVL_ST_DELAY:
|
||||
fprintf(out, "%*s#%lu\n", ind, "", ivl_stmt_delay_val(net));
|
||||
fprintf(out, "%*s#%llu\n", ind, "", ivl_stmt_delay_val(net));
|
||||
show_statement(ivl_stmt_sub_stmt(net), ind+2);
|
||||
break;
|
||||
|
||||
|
||||
@@ -4,3 +4,4 @@ functor:syn-rules
|
||||
functor:cprop
|
||||
functor:nodangle
|
||||
-t:dll
|
||||
flag:DLL=stub.tgt
|
||||
|
||||
+91
-12
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: stub.c,v 1.136 2006/01/02 05:33:20 steve Exp $"
|
||||
#ident "$Id: stub.c,v 1.140 2006/07/30 02:51:36 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -83,11 +83,29 @@ unsigned width_of_nexus(ivl_nexus_t nex)
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char*vt_type_string(ivl_expr_t net)
|
||||
ivl_variable_type_t type_of_nexus(ivl_nexus_t net)
|
||||
{
|
||||
unsigned idx;
|
||||
|
||||
for (idx = 0 ; idx < ivl_nexus_ptrs(net); idx += 1) {
|
||||
ivl_nexus_ptr_t ptr = ivl_nexus_ptr(net, idx);
|
||||
ivl_signal_t sig = ivl_nexus_ptr_sig(ptr);
|
||||
|
||||
if (sig != 0) {
|
||||
return ivl_signal_data_type(sig);
|
||||
}
|
||||
}
|
||||
|
||||
/* ERROR: A nexus should have at least one signal to carry
|
||||
properties like the data type. */
|
||||
return IVL_VT_NO_TYPE;
|
||||
}
|
||||
|
||||
const char*data_type_string(ivl_variable_type_t vtype)
|
||||
{
|
||||
const char*vt = "??";
|
||||
|
||||
switch (ivl_expr_value(net)) {
|
||||
switch (vtype) {
|
||||
case IVL_VT_NO_TYPE:
|
||||
vt = "NO_TYPE";
|
||||
break;
|
||||
@@ -108,6 +126,11 @@ const char*vt_type_string(ivl_expr_t net)
|
||||
return vt;
|
||||
}
|
||||
|
||||
const char*vt_type_string(ivl_expr_t net)
|
||||
{
|
||||
return data_type_string(ivl_expr_value(net));
|
||||
}
|
||||
|
||||
void show_binary_expression(ivl_expr_t net, unsigned ind)
|
||||
{
|
||||
unsigned width = ivl_expr_width(net);
|
||||
@@ -256,9 +279,8 @@ void show_expression(ivl_expr_t net, unsigned ind)
|
||||
break;
|
||||
|
||||
case IVL_EX_SFUNC:
|
||||
fprintf(out, "%*s<function=\"%s\", width=%u, %s, vt=%d>\n",
|
||||
ind, "", ivl_expr_name(net), ivl_expr_width(net),
|
||||
sign, ivl_expr_value(net));
|
||||
fprintf(out, "%*s<function=\"%s\", width=%u, %s, type=%s>\n",
|
||||
ind, "", ivl_expr_name(net), width, sign, vt);
|
||||
{ unsigned cnt = ivl_expr_parms(net);
|
||||
unsigned idx;
|
||||
for (idx = 0 ; idx < cnt ; idx += 1)
|
||||
@@ -762,14 +784,25 @@ static void show_lpm_re(ivl_lpm_t net)
|
||||
case IVL_LPM_RE_AND:
|
||||
type = "AND";
|
||||
break;
|
||||
case IVL_LPM_RE_NAND:
|
||||
type = "NAND";
|
||||
break;
|
||||
case IVL_LPM_RE_OR:
|
||||
type = "OR";
|
||||
break;
|
||||
case IVL_LPM_RE_NOR:
|
||||
type = "NOR";
|
||||
case IVL_LPM_RE_XOR:
|
||||
type = "XOR";
|
||||
break;
|
||||
case IVL_LPM_RE_XNOR:
|
||||
type = "XNOR";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
fprintf(out, " LPM_RE_%s: <width=%u>\n", type, width);
|
||||
fprintf(out, " LPM_RE_%s: %s <width=%u>\n",
|
||||
type, ivl_lpm_name(net),width);
|
||||
|
||||
nex = ivl_lpm_q(net, 0);
|
||||
fprintf(out, " Q: %s\n", ivl_nexus_name(nex));
|
||||
@@ -828,8 +861,9 @@ static void show_lpm_shift(ivl_lpm_t net, const char*shift_dir)
|
||||
ivl_nexus_t nex;
|
||||
unsigned width = ivl_lpm_width(net);
|
||||
|
||||
fprintf(out, " LPM_SHIFT%s %s: <width=%u>\n", shift_dir,
|
||||
ivl_lpm_basename(net), width);
|
||||
fprintf(out, " LPM_SHIFT%s %s: <width=%u, %ssigned>\n", shift_dir,
|
||||
ivl_lpm_basename(net), width,
|
||||
ivl_lpm_signed(net)? "" : "un");
|
||||
|
||||
nex = ivl_lpm_q(net, 0);
|
||||
fprintf(out, " Q: %s\n", ivl_nexus_name(nex));
|
||||
@@ -884,6 +918,34 @@ static void show_lpm_sub(ivl_lpm_t net)
|
||||
show_lpm_arithmetic_pins(net);
|
||||
}
|
||||
|
||||
static void show_lpm_sfunc(ivl_lpm_t net)
|
||||
{
|
||||
unsigned width = ivl_lpm_width(net);
|
||||
unsigned ports = ivl_lpm_size(net);
|
||||
ivl_variable_type_t data_type = type_of_nexus(ivl_lpm_q(net,0));
|
||||
ivl_nexus_t nex;
|
||||
unsigned idx;
|
||||
|
||||
fprintf(out, " LPM_SFUNC %s: <call=%s, width=%u, type=%s, ports=%u>\n",
|
||||
ivl_lpm_basename(net), ivl_lpm_string(net),
|
||||
width, data_type_string(data_type), ports);
|
||||
|
||||
nex = ivl_lpm_q(net, 0);
|
||||
if (width != width_of_nexus(nex)) {
|
||||
fprintf(out, " ERROR: Q output nexus width=%u "
|
||||
" does not match part width\n", width_of_nexus(nex));
|
||||
stub_errors += 1;
|
||||
}
|
||||
|
||||
fprintf(out, " Q: %s\n", ivl_nexus_name(nex));
|
||||
for (idx = 0 ; idx < ports ; idx += 1) {
|
||||
nex = ivl_lpm_data(net, idx);
|
||||
fprintf(out, " D%u: %s <width=%u, type=%s>\n", idx,
|
||||
ivl_nexus_name(nex), width_of_nexus(nex),
|
||||
data_type_string(type_of_nexus(nex)));
|
||||
}
|
||||
}
|
||||
|
||||
static void show_lpm_ufunc(ivl_lpm_t net)
|
||||
{
|
||||
unsigned width = ivl_lpm_width(net);
|
||||
@@ -954,10 +1016,11 @@ static void show_lpm(ivl_lpm_t net)
|
||||
break;
|
||||
|
||||
case IVL_LPM_RE_AND:
|
||||
show_lpm_re(net);
|
||||
break;
|
||||
|
||||
case IVL_LPM_RE_NAND:
|
||||
case IVL_LPM_RE_NOR:
|
||||
case IVL_LPM_RE_OR:
|
||||
case IVL_LPM_RE_XOR:
|
||||
case IVL_LPM_RE_XNOR:
|
||||
show_lpm_re(net);
|
||||
break;
|
||||
|
||||
@@ -1003,6 +1066,10 @@ static void show_lpm(ivl_lpm_t net)
|
||||
show_lpm_repeat(net);
|
||||
break;
|
||||
|
||||
case IVL_LPM_SFUNC:
|
||||
show_lpm_sfunc(net);
|
||||
break;
|
||||
|
||||
case IVL_LPM_UFUNC:
|
||||
show_lpm_ufunc(net);
|
||||
break;
|
||||
@@ -1580,6 +1647,18 @@ int target_design(ivl_design_t des)
|
||||
|
||||
/*
|
||||
* $Log: stub.c,v $
|
||||
* Revision 1.140 2006/07/30 02:51:36 steve
|
||||
* Fix/implement signed right shift.
|
||||
*
|
||||
* Revision 1.139 2006/06/18 04:15:50 steve
|
||||
* Add support for system functions in continuous assignments.
|
||||
*
|
||||
* Revision 1.138 2006/04/30 05:16:53 steve
|
||||
* Dump *all* the reduction operator gates.
|
||||
*
|
||||
* Revision 1.137 2006/04/27 04:26:38 steve
|
||||
* Dump function type as string.
|
||||
*
|
||||
* Revision 1.136 2006/01/02 05:33:20 steve
|
||||
* Node delays can be more general expressions in structural contexts.
|
||||
*
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
functor:cprop
|
||||
functor:nodangle
|
||||
-t:dll
|
||||
flag:DLL=stub.tgt
|
||||
|
||||
+9
-2
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: eval_real.c,v 1.14 2005/07/13 04:52:31 steve Exp $"
|
||||
#ident "$Id: eval_real.c,v 1.15 2006/08/09 05:19:08 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -80,6 +80,10 @@ static int draw_binary_real(ivl_expr_t exp)
|
||||
fprintf(vvp_out, " %%div/wr %d, %d;\n", l, r);
|
||||
break;
|
||||
|
||||
case '%':
|
||||
fprintf(vvp_out, " %%mod/wr %d, %d;\n", l, r);
|
||||
break;
|
||||
#if 0
|
||||
case '%':
|
||||
{ struct vector_info res = draw_eval_expr(exp, STUFF_OK_XZ);
|
||||
l = allocate_word();
|
||||
@@ -89,7 +93,7 @@ static int draw_binary_real(ivl_expr_t exp)
|
||||
clr_vector(res);
|
||||
}
|
||||
break;
|
||||
|
||||
#endif
|
||||
default:
|
||||
fprintf(stderr, "XXXX draw_binary_real(%c)\n",
|
||||
ivl_expr_opcode(exp));
|
||||
@@ -312,6 +316,9 @@ int draw_eval_real(ivl_expr_t exp)
|
||||
|
||||
/*
|
||||
* $Log: eval_real.c,v $
|
||||
* Revision 1.15 2006/08/09 05:19:08 steve
|
||||
* Add support for real valued modulus.
|
||||
*
|
||||
* Revision 1.14 2005/07/13 04:52:31 steve
|
||||
* Handle functions with real values.
|
||||
*
|
||||
|
||||
+31
-17
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: vvp_process.c,v 1.122 2006/02/02 02:43:59 steve Exp $"
|
||||
#ident "$Id: vvp_process.c,v 1.124 2006/08/08 05:11:37 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vvp_priv.h"
|
||||
@@ -76,24 +76,27 @@ static void set_to_lvariable(ivl_lval_t lval,
|
||||
{
|
||||
ivl_signal_t sig = ivl_lval_sig(lval);
|
||||
ivl_expr_t part_off_ex = ivl_lval_part_off(lval);
|
||||
unsigned part_off;
|
||||
unsigned part_off = 0;
|
||||
|
||||
if (part_off_ex == 0) {
|
||||
part_off = 0;
|
||||
} else {
|
||||
assert(number_is_immediate(part_off_ex, 64));
|
||||
} else if (number_is_immediate(part_off_ex, 64)) {
|
||||
part_off = get_number_immediate(part_off_ex);
|
||||
part_off_ex = 0;
|
||||
}
|
||||
|
||||
if (ivl_lval_mux(lval)) {
|
||||
if (ivl_lval_mux(lval))
|
||||
part_off_ex = ivl_lval_mux(lval);
|
||||
|
||||
if (part_off_ex) {
|
||||
unsigned skip_set = transient_id++;
|
||||
|
||||
/* There is a mux expression, so this must be a write to
|
||||
a bit-select leval. Presumably, the x0 index register
|
||||
a bit-select l-val. Presumably, the x0 index register
|
||||
has been loaded wit the result of the evaluated
|
||||
ivl_lval_mux expression. */
|
||||
part select base expression. */
|
||||
|
||||
draw_eval_expr_into_integer(ivl_lval_mux(lval), 0);
|
||||
draw_eval_expr_into_integer(part_off_ex, 0);
|
||||
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_set);
|
||||
|
||||
fprintf(vvp_out, " %%set/x0 V_%s, %u, %u;\n",
|
||||
@@ -103,7 +106,7 @@ static void set_to_lvariable(ivl_lval_t lval,
|
||||
} else if (part_off>0 || ivl_lval_width(lval)!=ivl_signal_width(sig)) {
|
||||
/* There is no mux expression, but a constant part
|
||||
offset. Load that into index x0 and generate a
|
||||
single-bit set instruction. */
|
||||
vector set instruction. */
|
||||
assert(ivl_lval_width(lval) == wid);
|
||||
|
||||
fprintf(vvp_out, " %%ix/load 0, %u;\n", part_off);
|
||||
@@ -152,20 +155,22 @@ static void assign_to_lvector(ivl_lval_t lval, unsigned bit,
|
||||
{
|
||||
ivl_signal_t sig = ivl_lval_sig(lval);
|
||||
ivl_expr_t part_off_ex = ivl_lval_part_off(lval);
|
||||
ivl_expr_t mux = ivl_lval_mux(lval);
|
||||
unsigned part_off;
|
||||
unsigned part_off = 0;
|
||||
|
||||
if (part_off_ex == 0) {
|
||||
part_off = 0;
|
||||
} else {
|
||||
assert(number_is_immediate(part_off_ex, 64));
|
||||
} else if (number_is_immediate(part_off_ex, 64)) {
|
||||
part_off = get_number_immediate(part_off_ex);
|
||||
part_off_ex = 0;
|
||||
}
|
||||
|
||||
if (mux != 0) {
|
||||
if (ivl_lval_mux(lval))
|
||||
part_off_ex = ivl_lval_mux(lval);
|
||||
|
||||
if (part_off_ex) {
|
||||
unsigned skip_assign = transient_id++;
|
||||
assert(dexp == 0);
|
||||
draw_eval_expr_into_integer(mux, 1);
|
||||
draw_eval_expr_into_integer(part_off_ex, 1);
|
||||
/* If the index expression has XZ bits, skip the assign. */
|
||||
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_assign);
|
||||
fprintf(vvp_out, " %%ix/load 0, %u;\n", width);
|
||||
@@ -902,10 +907,13 @@ static int show_stmt_condit(ivl_statement_t net, ivl_scope_t sscope)
|
||||
static int show_stmt_delay(ivl_statement_t net, ivl_scope_t sscope)
|
||||
{
|
||||
int rc = 0;
|
||||
unsigned long delay = ivl_stmt_delay_val(net);
|
||||
uint64_t delay = ivl_stmt_delay_val(net);
|
||||
ivl_statement_t stmt = ivl_stmt_sub_stmt(net);
|
||||
|
||||
fprintf(vvp_out, " %%delay %lu;\n", delay);
|
||||
unsigned long low = delay % UINT64_C(0x100000000);
|
||||
unsigned long hig = delay / UINT64_C(0x100000000);
|
||||
|
||||
fprintf(vvp_out, " %%delay %lu, %lu;\n", low, hig);
|
||||
/* Lots of things can happen during a delay. */
|
||||
clear_expression_lookaside();
|
||||
|
||||
@@ -1479,6 +1487,12 @@ int draw_func_definition(ivl_scope_t scope)
|
||||
|
||||
/*
|
||||
* $Log: vvp_process.c,v $
|
||||
* Revision 1.124 2006/08/08 05:11:37 steve
|
||||
* Handle 64bit delay constants.
|
||||
*
|
||||
* Revision 1.123 2006/04/16 00:15:43 steve
|
||||
* Fix part selects in l-values.
|
||||
*
|
||||
* Revision 1.122 2006/02/02 02:43:59 steve
|
||||
* Allow part selects of memory words in l-values.
|
||||
*
|
||||
|
||||
+61
-6
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: vvp_scope.c,v 1.143 2006/04/10 00:37:42 steve Exp $"
|
||||
#ident "$Id: vvp_scope.c,v 1.146 2006/07/30 02:51:36 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vvp_priv.h"
|
||||
@@ -611,6 +611,7 @@ static const char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr)
|
||||
case IVL_LPM_RE_NAND:
|
||||
case IVL_LPM_RE_NOR:
|
||||
case IVL_LPM_RE_XNOR:
|
||||
case IVL_LPM_SFUNC:
|
||||
case IVL_LPM_SHIFTL:
|
||||
case IVL_LPM_SHIFTR:
|
||||
case IVL_LPM_SIGN_EXT:
|
||||
@@ -1621,7 +1622,7 @@ static void draw_lpm_concat(ivl_lpm_t net)
|
||||
unsigned icnt = ivl_lpm_selects(net);
|
||||
|
||||
if (icnt <= 4) {
|
||||
/* This is the easies case. There are 4 or fewer input
|
||||
/* This is the easiest case. There are 4 or fewer input
|
||||
vectors, so the entire IVL_LPM_CONCAT can be
|
||||
implemented with a single .concat node. */
|
||||
draw_lpm_data_inputs(net, 0, icnt, src_table);
|
||||
@@ -1660,6 +1661,10 @@ static void draw_lpm_concat(ivl_lpm_t net)
|
||||
tree[idx/4].wid = wid;
|
||||
}
|
||||
|
||||
/* icnt is the input count for the level. It is the
|
||||
number of .concats of the previous level that have to
|
||||
be concatenated at the current level. (This is not
|
||||
the same as the bit width.) */
|
||||
icnt = (icnt + 3)/4;
|
||||
|
||||
/* Tree now has icnt nodes that are depth=0 concat nodes
|
||||
@@ -1682,8 +1687,8 @@ static void draw_lpm_concat(ivl_lpm_t net)
|
||||
net, depth, idx);
|
||||
|
||||
for (tdx = 0 ; tdx < trans ; tdx += 1) {
|
||||
fprintf(vvp_out, " %u", tree[idx].wid);
|
||||
wid += tree[idx].wid;
|
||||
fprintf(vvp_out, " %u", tree[idx+tdx].wid);
|
||||
wid += tree[idx+tdx].wid;
|
||||
}
|
||||
|
||||
for ( ; tdx < 4 ; tdx += 1)
|
||||
@@ -1783,10 +1788,10 @@ static void draw_lpm_ff(ivl_lpm_t net)
|
||||
static void draw_lpm_shiftl(ivl_lpm_t net)
|
||||
{
|
||||
unsigned width = ivl_lpm_width(net);
|
||||
|
||||
const char* signed_flag = ivl_lpm_signed(net)? "s" : "";
|
||||
|
||||
if (ivl_lpm_type(net) == IVL_LPM_SHIFTR)
|
||||
fprintf(vvp_out, "L_%p .shift/r %u", net, width);
|
||||
fprintf(vvp_out, "L_%p .shift/r%s %u", net, signed_flag, width);
|
||||
else
|
||||
fprintf(vvp_out, "L_%p .shift/l %u", net, width);
|
||||
|
||||
@@ -1797,6 +1802,43 @@ static void draw_lpm_shiftl(ivl_lpm_t net)
|
||||
fprintf(vvp_out, ";\n");
|
||||
}
|
||||
|
||||
static void draw_type_string_of_nex(ivl_nexus_t nex)
|
||||
{
|
||||
switch (data_type_of_nexus(nex)) {
|
||||
case IVL_VT_REAL:
|
||||
fprintf(vvp_out, "r");
|
||||
break;
|
||||
case IVL_VT_LOGIC:
|
||||
fprintf(vvp_out, "v%d", width_of_nexus(nex));
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void draw_lpm_sfunc(ivl_lpm_t net)
|
||||
{
|
||||
unsigned idx;
|
||||
fprintf(vvp_out, "L_%p .sfunc \"%s\"", net, ivl_lpm_string(net));
|
||||
|
||||
/* Print the function type descriptor string. */
|
||||
fprintf(vvp_out, ", \"");
|
||||
|
||||
draw_type_string_of_nex(ivl_lpm_q(net,0));
|
||||
|
||||
for (idx = 0 ; idx < ivl_lpm_size(net) ; idx += 1)
|
||||
draw_type_string_of_nex(ivl_lpm_data(net,idx));
|
||||
|
||||
fprintf(vvp_out, "\"");
|
||||
|
||||
for (idx = 0 ; idx < ivl_lpm_size(net) ; idx += 1) {
|
||||
fprintf(vvp_out, ", %s", draw_net_input(ivl_lpm_data(net,idx)));
|
||||
}
|
||||
|
||||
fprintf(vvp_out, ";\n");
|
||||
}
|
||||
|
||||
static void draw_lpm_ufunc(ivl_lpm_t net)
|
||||
{
|
||||
unsigned idx;
|
||||
@@ -2074,6 +2116,10 @@ static void draw_lpm_in_scope(ivl_lpm_t net)
|
||||
draw_lpm_sign_ext(net);
|
||||
return;
|
||||
|
||||
case IVL_LPM_SFUNC:
|
||||
draw_lpm_sfunc(net);
|
||||
return;
|
||||
|
||||
case IVL_LPM_UFUNC:
|
||||
draw_lpm_ufunc(net);
|
||||
return;
|
||||
@@ -2205,6 +2251,15 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent)
|
||||
|
||||
/*
|
||||
* $Log: vvp_scope.c,v $
|
||||
* Revision 1.146 2006/07/30 02:51:36 steve
|
||||
* Fix/implement signed right shift.
|
||||
*
|
||||
* Revision 1.145 2006/06/18 04:15:50 steve
|
||||
* Add support for system functions in continuous assignments.
|
||||
*
|
||||
* Revision 1.144 2006/04/22 04:27:36 steve
|
||||
* Get tail counts right in nested concatenations.
|
||||
*
|
||||
* Revision 1.143 2006/04/10 00:37:42 steve
|
||||
* Add support for generate loops w/ wires and gates.
|
||||
*
|
||||
|
||||
+5
-5
@@ -1,10 +1,10 @@
|
||||
Summary: Icarus Verilog
|
||||
Name: verilog
|
||||
Version: 0.9.0.20060409
|
||||
Version: 0.9.0.20060809
|
||||
Release: 0
|
||||
Copyright: GPL
|
||||
License: GPL
|
||||
Group: Applications/Engineering
|
||||
Source: ftp://icarus.com/pub/eda/verilog//verilog-20060409.tar.gz
|
||||
Source: ftp://icarus.com/pub/eda/verilog//verilog-20060809.tar.gz
|
||||
URL: http://www.icarus.com/eda/verilog/index.html
|
||||
Packager: Stephen Williams <[email protected]>
|
||||
|
||||
@@ -22,7 +22,7 @@ engineering formats, including simulation. It strives to be true
|
||||
to the IEEE-1364 standard.
|
||||
|
||||
%prep
|
||||
%setup -n verilog-20060409
|
||||
%setup -n verilog-20060809
|
||||
|
||||
%build
|
||||
%ifarch x86_64
|
||||
@@ -41,7 +41,7 @@ make prefix=$RPM_BUILD_ROOT/usr install
|
||||
%attr(-,root,root) %doc examples/*
|
||||
|
||||
%attr(-,root,root) /usr/man/man1/iverilog.1.gz
|
||||
%attr(-,root,root) /usr/man/man1/iverilog-fpga.1.gz
|
||||
#%attr(-,root,root) /usr/man/man1/iverilog-fpga.1.gz
|
||||
%attr(-,root,root) /usr/man/man1/iverilog-vpi.1.gz
|
||||
%attr(-,root,root) /usr/man/man1/vvp.1.gz
|
||||
|
||||
|
||||
+118
-25
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: verinum.cc,v 1.44 2005/12/07 04:04:24 steve Exp $"
|
||||
#ident "$Id: verinum.cc,v 1.48 2006/08/08 05:11:37 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -87,14 +87,14 @@ verinum::verinum(verinum::V val, unsigned n, bool h)
|
||||
bits_[idx] = val;
|
||||
}
|
||||
|
||||
verinum::verinum(unsigned long val, unsigned n)
|
||||
verinum::verinum(uint64_t val, unsigned n)
|
||||
: has_len_(true), has_sign_(false), string_flag_(false)
|
||||
{
|
||||
nbits_ = n;
|
||||
bits_ = new V[nbits_];
|
||||
for (unsigned idx = 0 ; idx < nbits_ ; idx += 1) {
|
||||
bits_[idx] = (val&1) ? V1 : V0;
|
||||
val >>= 1;
|
||||
val >>= (uint64_t)1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,10 +134,10 @@ verinum::verinum(const verinum&that, unsigned nbits)
|
||||
}
|
||||
}
|
||||
|
||||
verinum::verinum(long that)
|
||||
verinum::verinum(int64_t that)
|
||||
: has_len_(false), has_sign_(true), string_flag_(false)
|
||||
{
|
||||
long tmp;
|
||||
int64_t tmp;
|
||||
|
||||
tmp = that/2;
|
||||
nbits_ = 1;
|
||||
@@ -208,6 +208,27 @@ unsigned long verinum::as_ulong() const
|
||||
return val;
|
||||
}
|
||||
|
||||
uint64_t verinum::as_ulong64() const
|
||||
{
|
||||
if (nbits_ == 0)
|
||||
return 0;
|
||||
|
||||
if (!is_defined())
|
||||
return 0;
|
||||
|
||||
unsigned top = nbits_;
|
||||
if (top >= (8 * sizeof(uint64_t)))
|
||||
top = 8 * sizeof(uint64_t);
|
||||
|
||||
uint64_t val = 0;
|
||||
uint64_t mask = 1;
|
||||
for (unsigned idx = 0 ; idx < top ; idx += 1, mask <<= 1)
|
||||
if (bits_[idx] == V1)
|
||||
val |= mask;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function returns the native long integer that represents the
|
||||
* value of this object. It accounts for sign extension if the value
|
||||
@@ -317,6 +338,30 @@ bool verinum::is_zero() const
|
||||
return true;
|
||||
}
|
||||
|
||||
verinum pad_to_width(const verinum&that, unsigned width)
|
||||
{
|
||||
if (that.len() >= width)
|
||||
return that;
|
||||
|
||||
if (that.len() == 0) {
|
||||
verinum val (verinum::V0, width, that.has_len());
|
||||
val.has_sign(that.has_sign());
|
||||
return val;
|
||||
}
|
||||
|
||||
verinum::V pad = that[that.len()-1];
|
||||
if (pad==verinum::V1 && !that.has_sign())
|
||||
pad = verinum::V0;
|
||||
|
||||
verinum val(pad, width, that.has_len());
|
||||
|
||||
for (unsigned idx = 0 ; idx < that.len() ; idx += 1)
|
||||
val.set(idx, that[idx]);
|
||||
|
||||
val.has_sign(that.has_sign());
|
||||
return val;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function returns a version of the verinum that has only as
|
||||
* many bits as are needed to accurately represent the value. It takes
|
||||
@@ -423,7 +468,7 @@ ostream& operator<< (ostream&o, const verinum&v)
|
||||
|
||||
/* If the number is fully defined (no x or z) then print it
|
||||
out as a decimal number. */
|
||||
if (v.is_defined()) {
|
||||
if (v.is_defined() && v.len() < sizeof(long)) {
|
||||
if (v.has_sign())
|
||||
o << "'sd" << v.as_long();
|
||||
else
|
||||
@@ -612,7 +657,7 @@ verinum operator + (const verinum&left, const verinum&right)
|
||||
val_bits[idx] = add_with_carry(left[idx], right[idx], carry);
|
||||
|
||||
verinum::V rpad = signed_flag? right[right.len()-1] : verinum::V0;
|
||||
verinum::V lpad = signed_flag? left[left.len()-1] : verinum::V0;
|
||||
verinum::V lpad = signed_flag? left[left.len()-1] : verinum::V0;
|
||||
|
||||
if (left.len() > right.len()) {
|
||||
|
||||
@@ -639,35 +684,46 @@ verinum operator + (const verinum&left, const verinum&right)
|
||||
return val;
|
||||
}
|
||||
|
||||
verinum operator - (const verinum&left, const verinum&r)
|
||||
verinum operator - (const verinum&left, const verinum&right)
|
||||
{
|
||||
verinum right;
|
||||
unsigned min = left.len();
|
||||
if (r.len() < min) {
|
||||
right = verinum(verinum::V0, min);
|
||||
for (unsigned idx = 0 ; idx < r.len() ; idx += 1)
|
||||
right.set(idx, r[idx]);
|
||||
|
||||
} else {
|
||||
right = r;
|
||||
}
|
||||
|
||||
right = v_not(right);
|
||||
if (right.len() < min) min = right.len();
|
||||
|
||||
unsigned max = left.len();
|
||||
if (right.len() > max) max = right.len();
|
||||
|
||||
verinum val (verinum::V0, max);
|
||||
bool signed_flag = left.has_sign() && right.has_sign();
|
||||
verinum::V*val_bits = new verinum::V[max+1];
|
||||
|
||||
verinum::V carry = verinum::V1;
|
||||
for (unsigned idx = 0 ; idx < min ; idx += 1)
|
||||
val.set(idx, add_with_carry(left[idx], right[idx], carry));
|
||||
val_bits[idx] = add_with_carry(left[idx], ~right[idx], carry);
|
||||
|
||||
assert(left.len() <= right.len());
|
||||
for (unsigned idx = min ; idx < max ; idx += 1)
|
||||
val.set(idx, add_with_carry(verinum::V0, right[idx], carry));
|
||||
verinum::V rpad = signed_flag? ~right[right.len()-1] : verinum::V1;
|
||||
verinum::V lpad = signed_flag? left[left.len()-1] : verinum::V0;
|
||||
|
||||
if (left.len() > right.len()) {
|
||||
|
||||
for (unsigned idx = min ; idx < left.len() ; idx += 1)
|
||||
val_bits[idx] = add_with_carry(left[idx], rpad, carry);
|
||||
|
||||
} else {
|
||||
|
||||
for (unsigned idx = min ; idx < right.len() ; idx += 1)
|
||||
val_bits[idx] = add_with_carry(lpad, ~right[idx], carry);
|
||||
}
|
||||
|
||||
if (signed_flag) {
|
||||
val_bits[max] = add_with_carry(lpad, rpad, carry);
|
||||
if (val_bits[max] != val_bits[max-1])
|
||||
max += 1;
|
||||
}
|
||||
|
||||
verinum val (val_bits, max, false);
|
||||
val.has_sign(signed_flag);
|
||||
|
||||
delete[]val_bits;
|
||||
|
||||
val.has_sign(left.has_sign() && r.has_sign());
|
||||
return val;
|
||||
}
|
||||
|
||||
@@ -714,6 +770,17 @@ verinum operator * (const verinum&left, const verinum&right)
|
||||
return trim_vnum(result);
|
||||
}
|
||||
|
||||
verinum pow(const verinum&left, const verinum&right)
|
||||
{
|
||||
verinum result = left;
|
||||
unsigned pow_count = right.as_ulong();
|
||||
|
||||
for (unsigned idx = 1 ; idx < pow_count ; idx += 1)
|
||||
result = result * result;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
verinum operator << (const verinum&that, unsigned shift)
|
||||
{
|
||||
verinum result(verinum::V0, that.len() + shift, that.has_len());
|
||||
@@ -920,6 +987,18 @@ verinum concat(const verinum&left, const verinum&right)
|
||||
return res;
|
||||
}
|
||||
|
||||
verinum::V operator ~ (verinum::V l)
|
||||
{
|
||||
switch (l) {
|
||||
case verinum::V0:
|
||||
return verinum::V1;
|
||||
case verinum::V1:
|
||||
return verinum::V0;
|
||||
default:
|
||||
return verinum::Vx;
|
||||
}
|
||||
}
|
||||
|
||||
verinum::V operator | (verinum::V l, verinum::V r)
|
||||
{
|
||||
if (l == verinum::V1)
|
||||
@@ -960,6 +1039,20 @@ verinum::V operator ^ (verinum::V l, verinum::V r)
|
||||
|
||||
/*
|
||||
* $Log: verinum.cc,v $
|
||||
* Revision 1.48 2006/08/08 05:11:37 steve
|
||||
* Handle 64bit delay constants.
|
||||
*
|
||||
* Revision 1.47 2006/07/31 03:50:17 steve
|
||||
* Add support for power in constant expressions.
|
||||
*
|
||||
* Revision 1.46 2006/06/02 04:48:50 steve
|
||||
* Make elaborate_expr methods aware of the width that the context
|
||||
* requires of it. In the process, fix sizing of the width of unary
|
||||
* minus is context determined sizes.
|
||||
*
|
||||
* Revision 1.45 2006/06/01 03:54:51 steve
|
||||
* Fix broken subtraction of small constants.
|
||||
*
|
||||
* Revision 1.44 2005/12/07 04:04:24 steve
|
||||
* Allow constant concat expressions.
|
||||
*
|
||||
|
||||
@@ -19,10 +19,11 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: verinum.h,v 1.28 2005/12/07 04:04:24 steve Exp $"
|
||||
#ident "$Id: verinum.h,v 1.32 2006/08/08 05:11:37 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <string>
|
||||
# include <stdint.h>
|
||||
|
||||
# include "config.h"
|
||||
#ifdef HAVE_IOSFWD
|
||||
@@ -48,11 +49,11 @@ class verinum {
|
||||
verinum(const string&str);
|
||||
verinum(const V*v, unsigned nbits, bool has_len =true);
|
||||
verinum(V, unsigned nbits =1, bool has_len =true);
|
||||
verinum(unsigned long val, unsigned bits);
|
||||
verinum(uint64_t val, unsigned bits);
|
||||
verinum(const verinum&);
|
||||
|
||||
// Create a signed number, with an unspecified number of bits.
|
||||
explicit verinum(long val);
|
||||
explicit verinum(int64_t val);
|
||||
|
||||
// Copy only the specified number of bits from the
|
||||
// source. Also mark this number as has_len.
|
||||
@@ -90,6 +91,7 @@ class verinum {
|
||||
V operator[] (unsigned idx) const { return get(idx); }
|
||||
|
||||
|
||||
uint64_t as_ulong64() const;
|
||||
unsigned long as_ulong() const;
|
||||
signed long as_long() const;
|
||||
string as_string() const;
|
||||
@@ -105,6 +107,11 @@ class verinum {
|
||||
bool string_flag_;
|
||||
};
|
||||
|
||||
/* Return a verinum that has the same value as the input, but is at
|
||||
least as wide as the requested width. This may involve sign
|
||||
extension, if the value is signed. */
|
||||
extern verinum pad_to_width(const verinum&, unsigned width);
|
||||
|
||||
/* Return a verinum that is minimal. That is, it has only the length
|
||||
needed to accurately represent the contained value, signed or not. */
|
||||
extern verinum trim_vnum(const verinum&);
|
||||
@@ -112,6 +119,7 @@ extern verinum trim_vnum(const verinum&);
|
||||
extern ostream& operator<< (ostream&, const verinum&);
|
||||
extern ostream& operator<< (ostream&, verinum::V);
|
||||
|
||||
extern verinum::V operator ~ (verinum::V l);
|
||||
extern verinum::V operator | (verinum::V l, verinum::V r);
|
||||
extern verinum::V operator & (verinum::V l, verinum::V r);
|
||||
extern verinum::V operator ^ (verinum::V l, verinum::V r);
|
||||
@@ -141,6 +149,8 @@ extern verinum operator * (const verinum&left, const verinum&right);
|
||||
extern verinum operator / (const verinum&left, const verinum&right);
|
||||
extern verinum operator % (const verinum&left, const verinum&right);
|
||||
|
||||
extern verinum pow(const verinum&left, const verinum&right);
|
||||
|
||||
extern verinum operator<< (const verinum&left, unsigned shift);
|
||||
extern verinum operator>> (const verinum&left, unsigned shift);
|
||||
|
||||
@@ -151,6 +161,20 @@ extern verinum v_not(const verinum&left);
|
||||
|
||||
/*
|
||||
* $Log: verinum.h,v $
|
||||
* Revision 1.32 2006/08/08 05:11:37 steve
|
||||
* Handle 64bit delay constants.
|
||||
*
|
||||
* Revision 1.31 2006/07/31 03:50:17 steve
|
||||
* Add support for power in constant expressions.
|
||||
*
|
||||
* Revision 1.30 2006/06/02 04:48:50 steve
|
||||
* Make elaborate_expr methods aware of the width that the context
|
||||
* requires of it. In the process, fix sizing of the width of unary
|
||||
* minus is context determined sizes.
|
||||
*
|
||||
* Revision 1.29 2006/06/01 03:54:51 steve
|
||||
* Fix broken subtraction of small constants.
|
||||
*
|
||||
* Revision 1.28 2005/12/07 04:04:24 steve
|
||||
* Allow constant concat expressions.
|
||||
*
|
||||
|
||||
+31
-1
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: verireal.cc,v 1.15 2004/06/04 23:33:51 steve Exp $"
|
||||
#ident "$Id: verireal.cc,v 1.17 2006/08/08 05:11:37 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -77,6 +77,23 @@ long verireal::as_long(int shift) const
|
||||
return (long) outf;
|
||||
}
|
||||
|
||||
int64_t verireal::as_long64(int shift) const
|
||||
{
|
||||
double out = value_ * pow(10.0,shift);
|
||||
double outf;
|
||||
|
||||
if (out >= 0.0) {
|
||||
outf = floor(out);
|
||||
if (out >= (outf + 0.5))
|
||||
outf += 1.0;
|
||||
} else {
|
||||
outf = ceil(out);
|
||||
if (out <= (outf - 0.5))
|
||||
outf -= 1.0;
|
||||
}
|
||||
return (int64_t) outf;
|
||||
}
|
||||
|
||||
double verireal::as_double() const
|
||||
{
|
||||
return value_;
|
||||
@@ -117,6 +134,13 @@ verireal operator% (const verireal&l, const verinum&r)
|
||||
return res;
|
||||
}
|
||||
|
||||
verireal pow (const verireal&l, const verireal&r)
|
||||
{
|
||||
verireal res;
|
||||
res.value_ = pow(l.value_, r.value_);
|
||||
return res;
|
||||
}
|
||||
|
||||
verireal operator- (const verireal&l)
|
||||
{
|
||||
verireal res;
|
||||
@@ -132,6 +156,12 @@ ostream& operator<< (ostream&out, const verireal&v)
|
||||
|
||||
/*
|
||||
* $Log: verireal.cc,v $
|
||||
* Revision 1.17 2006/08/08 05:11:37 steve
|
||||
* Handle 64bit delay constants.
|
||||
*
|
||||
* Revision 1.16 2006/07/31 03:50:18 steve
|
||||
* Add support for power in constant expressions.
|
||||
*
|
||||
* Revision 1.15 2004/06/04 23:33:51 steve
|
||||
* Add unary minus as operator supported by verireal.
|
||||
*
|
||||
|
||||
+12
-1
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: verireal.h,v 1.11 2005/06/14 19:13:43 steve Exp $"
|
||||
#ident "$Id: verireal.h,v 1.13 2006/08/08 05:11:37 steve Exp $"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_IOSFWD
|
||||
@@ -28,6 +28,8 @@
|
||||
class ostream;
|
||||
#endif
|
||||
|
||||
# include <stdint.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
class verinum;
|
||||
@@ -47,6 +49,7 @@ class verireal {
|
||||
friend verireal operator/ (const verireal&, const verinum&);
|
||||
friend verireal operator% (const verireal&, const verireal&);
|
||||
friend verireal operator% (const verireal&, const verinum&);
|
||||
friend verireal pow(const verireal&, const verireal&);
|
||||
|
||||
// Unary minus.
|
||||
friend verireal operator- (const verireal&);
|
||||
@@ -63,6 +66,7 @@ class verireal {
|
||||
example if the value is 2.5 and shift == 1, the result
|
||||
is 25. */
|
||||
long as_long(int shift =0) const;
|
||||
int64_t as_long64(int shift =0) const;
|
||||
|
||||
double as_double() const;
|
||||
|
||||
@@ -76,10 +80,17 @@ extern verireal operator/ (const verireal&, const verireal&);
|
||||
extern verireal operator/ (const verireal&, const verinum&);
|
||||
extern verireal operator% (const verireal&, const verireal&);
|
||||
extern verireal operator% (const verireal&, const verinum&);
|
||||
extern verireal pow(const verireal&, const verireal&);
|
||||
extern verireal operator- (const verireal&);
|
||||
|
||||
/*
|
||||
* $Log: verireal.h,v $
|
||||
* Revision 1.13 2006/08/08 05:11:37 steve
|
||||
* Handle 64bit delay constants.
|
||||
*
|
||||
* Revision 1.12 2006/07/31 03:50:18 steve
|
||||
* Add support for power in constant expressions.
|
||||
*
|
||||
* Revision 1.11 2005/06/14 19:13:43 steve
|
||||
* gcc3/4 compile errors.
|
||||
*
|
||||
|
||||
+2
-2
@@ -16,7 +16,7 @@
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.58 2004/10/04 01:09:22 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.59 2006/08/03 05:06:04 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
@@ -65,7 +65,7 @@ dep:
|
||||
|
||||
O = sys_table.o sys_convert.o sys_deposit.o sys_display.o sys_fileio.o \
|
||||
sys_finish.o sys_plusargs.o sys_random.o sys_random_mti.o \
|
||||
sys_readmem.o sys_readmem_lex.o \
|
||||
sys_readmem.o sys_readmem_lex.o sys_scanf.o \
|
||||
sys_time.o sys_vcd.o sys_vcdoff.o vcd_priv.o mt19937int.o priv.o stringheap.o
|
||||
|
||||
ifeq (@HAVE_LIBZ@,yes)
|
||||
|
||||
+58
-24
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: sys_fileio.c,v 1.7 2005/09/20 18:34:01 steve Exp $"
|
||||
#ident "$Id: sys_fileio.c,v 1.8 2006/08/03 05:02:46 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vpi_user.h"
|
||||
@@ -33,6 +33,54 @@
|
||||
/*
|
||||
* Implement the $fopen system function.
|
||||
*/
|
||||
static int sys_fopen_compiletf(char *name)
|
||||
{
|
||||
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
|
||||
vpiHandle argv = vpi_iterate(vpiArgument, sys);
|
||||
vpiHandle item;
|
||||
|
||||
if (argv == 0) {
|
||||
vpi_printf("%s: file name argument missing.\n", name);
|
||||
vpi_sim_control(vpiFinish, -1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
item = vpi_scan(argv);
|
||||
if (item == 0) {
|
||||
vpi_printf("%s: file name argument missing.\n", name);
|
||||
vpi_sim_control(vpiFinish, -1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
item = vpi_scan(argv);
|
||||
if (item == 0) {
|
||||
/* The mode argument is optional. It is OK for it
|
||||
to be missing. In this case, there are no more
|
||||
arguments, and we're done. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (! is_constant(item)) {
|
||||
vpi_printf("ERROR: %s mode argument must be a constant\n", name);
|
||||
vpi_sim_control(vpiFinish, -1);
|
||||
}
|
||||
|
||||
if (vpi_get(vpiConstType, item) != vpiStringConst) {
|
||||
vpi_printf("ERROR: %s mode argument must be a string.\n", name);
|
||||
vpi_sim_control(vpiFinish, -1);
|
||||
}
|
||||
|
||||
item = vpi_scan(argv);
|
||||
if (item == 0) {
|
||||
/* There should be no more arguments. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
vpi_free_object(argv);
|
||||
vpi_printf("%s: Too many arguments to system function.\n", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sys_fopen_calltf(char *name)
|
||||
{
|
||||
s_vpi_value value;
|
||||
@@ -40,33 +88,17 @@ static int sys_fopen_calltf(char *name)
|
||||
|
||||
vpiHandle call_handle = vpi_handle(vpiSysTfCall, 0);
|
||||
vpiHandle argv = vpi_iterate(vpiArgument, call_handle);
|
||||
vpiHandle item = argv ? vpi_scan(argv) : 0;
|
||||
vpiHandle mode = item ? vpi_scan(argv) : 0;
|
||||
vpiHandle item = vpi_scan(argv);
|
||||
vpiHandle mode = vpi_scan(argv);
|
||||
|
||||
if (item == 0) {
|
||||
vpi_printf("%s: file name parameter missing.\n", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (mode == 0) {
|
||||
argv = 0;
|
||||
}
|
||||
assert(item);
|
||||
|
||||
if (mode) {
|
||||
if (! is_constant(mode)) {
|
||||
vpi_printf("ERROR: %s parameter must be a constant\n", name);
|
||||
if (argv) vpi_free_object(argv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (vpi_get(vpiConstType, mode) != vpiStringConst) {
|
||||
vpi_printf("ERROR: %s parameter must be a string.\n", name);
|
||||
if (argv) vpi_free_object(argv);
|
||||
return 0;
|
||||
}
|
||||
value.format = vpiStringVal;
|
||||
vpi_get_value(mode, &value);
|
||||
mode_string = strdup(value.value.str);
|
||||
|
||||
vpi_free_object(argv);
|
||||
}
|
||||
|
||||
/* Get the string form of the file name from the file name
|
||||
@@ -79,7 +111,6 @@ static int sys_fopen_calltf(char *name)
|
||||
" does not have a string value\n",
|
||||
name, vpi_get(vpiType, item));
|
||||
if (mode) free(mode_string);
|
||||
if (argv) vpi_free_object(argv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -413,7 +444,7 @@ void sys_fileio_register()
|
||||
tf_data.type = vpiSysFunc;
|
||||
tf_data.tfname = "$fopen";
|
||||
tf_data.calltf = sys_fopen_calltf;
|
||||
tf_data.compiletf = 0;
|
||||
tf_data.compiletf = sys_fopen_compiletf;
|
||||
tf_data.sizetf = sys_fopen_sizetf;
|
||||
tf_data.user_data = "$fopen";
|
||||
vpi_register_systf(&tf_data);
|
||||
@@ -479,6 +510,9 @@ void sys_fileio_register()
|
||||
|
||||
/*
|
||||
* $Log: sys_fileio.c,v $
|
||||
* Revision 1.8 2006/08/03 05:02:46 steve
|
||||
* Use compiletf to check arguments.
|
||||
*
|
||||
* Revision 1.7 2005/09/20 18:34:01 steve
|
||||
* Clean up compiler warnings.
|
||||
*
|
||||
|
||||
+22
-1
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: sys_readmem.c,v 1.16 2004/10/04 01:10:58 steve Exp $"
|
||||
#ident "$Id: sys_readmem.c,v 1.17 2006/04/25 05:00:12 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vpi_config.h"
|
||||
@@ -134,6 +134,9 @@ static int sys_readmem_calltf(char*name)
|
||||
start_addr<stop_addr or vice versa if not... */
|
||||
unsigned min_addr, max_addr;
|
||||
|
||||
/* This is the number of words that we need from the memory. */
|
||||
unsigned word_count;
|
||||
|
||||
|
||||
/*======================================== Get parameters */
|
||||
|
||||
@@ -252,6 +255,9 @@ static int sys_readmem_calltf(char*name)
|
||||
min_addr = start_addr<stop_addr ? start_addr : stop_addr ;
|
||||
max_addr = start_addr<stop_addr ? stop_addr : start_addr;
|
||||
|
||||
/* We need this many words from the file. */
|
||||
word_count = max_addr-min_addr+1;
|
||||
|
||||
/* Check that start_addr and stop_addr are within the memory
|
||||
range */
|
||||
if (left_addr<right_addr){
|
||||
@@ -304,6 +310,11 @@ static int sys_readmem_calltf(char*name)
|
||||
switch (code) {
|
||||
case MEM_ADDRESS:
|
||||
addr = value.value.vector->aval;
|
||||
/* if there is an address in the memory file, then
|
||||
turn off any possible warnings about not having
|
||||
enough words to load the memory. This is standard
|
||||
behavior. */
|
||||
word_count = 0;
|
||||
break;
|
||||
|
||||
case MEM_WORD:
|
||||
@@ -311,6 +322,9 @@ static int sys_readmem_calltf(char*name)
|
||||
word_index = vpi_handle_by_index(mitem, addr);
|
||||
assert(word_index);
|
||||
vpi_put_value(word_index, &value, 0, vpiNoDelay);
|
||||
|
||||
if (word_count > 0)
|
||||
word_count -= 1;
|
||||
}
|
||||
else{
|
||||
vpi_printf("%s(%s): address (0x%x) out of range (0x%x:0x%x)\n",
|
||||
@@ -327,6 +341,10 @@ static int sys_readmem_calltf(char*name)
|
||||
}
|
||||
}
|
||||
|
||||
if (word_count > 0)
|
||||
vpi_printf("%s(%s): Not enough words in the read file "
|
||||
"for requested range.\n", name, path);
|
||||
|
||||
bailout:
|
||||
free(value.value.vector);
|
||||
|
||||
@@ -576,6 +594,9 @@ void sys_readmem_register()
|
||||
|
||||
/*
|
||||
* $Log: sys_readmem.c,v $
|
||||
* Revision 1.17 2006/04/25 05:00:12 steve
|
||||
* Warning when file is inadequate for requested range.
|
||||
*
|
||||
* Revision 1.16 2004/10/04 01:10:58 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
||||
+378
@@ -0,0 +1,378 @@
|
||||
/*
|
||||
* Copyright (c) 2006 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
|
||||
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: sys_scanf.c,v 1.1 2006/08/03 05:06:04 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vpi_user.h"
|
||||
# include "sys_priv.h"
|
||||
# include <ctype.h>
|
||||
# include <string.h>
|
||||
# include <stdio.h>
|
||||
# include <stdlib.h>
|
||||
# include <assert.h>
|
||||
|
||||
struct byte_source {
|
||||
const char*str;
|
||||
FILE*fd;
|
||||
};
|
||||
|
||||
static int byte_getc(struct byte_source*byte)
|
||||
{
|
||||
if (byte->str) {
|
||||
if (byte->str[0] == 0)
|
||||
return EOF;
|
||||
else
|
||||
return *(byte->str)++;
|
||||
}
|
||||
|
||||
return fgetc(byte->fd);
|
||||
}
|
||||
|
||||
static void byte_ungetc(struct byte_source*src, int ch)
|
||||
{
|
||||
if (ch == EOF)
|
||||
return;
|
||||
|
||||
if (src->str) {
|
||||
src->str -= 1;
|
||||
return;
|
||||
}
|
||||
|
||||
assert(src->fd);
|
||||
ungetc(ch, src->fd);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The $fscanf and $sscanf functions are the same except for the first
|
||||
* argument, which is the source. The wrapper functions below peel off
|
||||
* the first argument and make a byte_source object that then gets
|
||||
* passed to this function, which processes the rest of the function.
|
||||
*/
|
||||
static int scan_format(vpiHandle sys, struct byte_source*src, vpiHandle argv)
|
||||
{
|
||||
s_vpi_value val;
|
||||
vpiHandle item;
|
||||
|
||||
char*fmt, *fmtp;
|
||||
int rc = 0;
|
||||
int ch;
|
||||
|
||||
item = vpi_scan(argv);
|
||||
assert(item);
|
||||
|
||||
val.format = vpiStringVal;
|
||||
vpi_get_value(item, &val);
|
||||
fmtp = fmt = strdup(val.value.str);
|
||||
|
||||
while ( fmtp && *fmtp != 0 ) {
|
||||
|
||||
if (isspace(*fmtp)) {
|
||||
/* White space matches a string of white space in
|
||||
the input. The number of spaces is not
|
||||
relevent, and the match may be 0 or more
|
||||
spaces. */
|
||||
while (*fmtp && isspace(*fmtp))
|
||||
fmtp += 1;
|
||||
|
||||
ch = byte_getc(src);
|
||||
while (isspace(ch))
|
||||
ch = byte_getc(src);
|
||||
|
||||
if (ch != EOF)
|
||||
byte_ungetc(src, ch);
|
||||
|
||||
} else if (*fmtp != '%') {
|
||||
/* Characters other then % match themselves. */
|
||||
ch = byte_getc(src);
|
||||
if (ch != *fmtp) {
|
||||
byte_ungetc(src, ch);
|
||||
break;
|
||||
}
|
||||
|
||||
fmtp += 1;
|
||||
|
||||
} else {
|
||||
|
||||
/* We are at a pattern character. The pattern has
|
||||
the format %<N>x no matter what the x code, so
|
||||
parse it generically first. */
|
||||
|
||||
int suppress_flag = 0;
|
||||
int length_field = -1;
|
||||
int code = 0;
|
||||
int sign_flag = 1;
|
||||
PLI_INT32 value;
|
||||
|
||||
char*tmp;
|
||||
|
||||
fmtp += 1;
|
||||
if (*fmtp == '*') {
|
||||
suppress_flag = 1;
|
||||
fmtp += 1;
|
||||
}
|
||||
if (isdigit(*fmtp)) {
|
||||
length_field = 0;
|
||||
while (isdigit(*fmtp)) {
|
||||
length_field *= 10;
|
||||
length_field += *fmtp - '0';
|
||||
fmtp += 1;
|
||||
}
|
||||
}
|
||||
|
||||
code = *fmtp;
|
||||
fmtp += 1;
|
||||
|
||||
switch (code) {
|
||||
case '%':
|
||||
ch = byte_getc(src);
|
||||
if (ch != '%') {
|
||||
byte_ungetc(src, ch);
|
||||
fmtp = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
/* binary integer */
|
||||
tmp = malloc(2);
|
||||
value = 0;
|
||||
tmp[0] = 0;
|
||||
|
||||
ch = byte_getc(src);
|
||||
while (strchr("01xXzZ?_", ch)) {
|
||||
if (ch == '?')
|
||||
ch = 'x';
|
||||
if (ch != '_') {
|
||||
ch = tolower(ch);
|
||||
tmp[value++] = ch;
|
||||
tmp = realloc(tmp, value+1);
|
||||
tmp[value] = 0;
|
||||
}
|
||||
ch = byte_getc(src);
|
||||
}
|
||||
byte_ungetc(src, ch);
|
||||
|
||||
item = vpi_scan(argv);
|
||||
assert(item);
|
||||
|
||||
val.format = vpiBinStrVal;
|
||||
val.value.str = tmp;
|
||||
vpi_put_value(item, &val, 0, vpiNoDelay);
|
||||
|
||||
free(tmp);
|
||||
rc += 1;
|
||||
break;
|
||||
|
||||
|
||||
case 'd':
|
||||
/* Decimal integer */
|
||||
ch = byte_getc(src);
|
||||
if (ch == '-') {
|
||||
sign_flag = -1;
|
||||
ch = byte_getc(src);
|
||||
}
|
||||
value = 0;
|
||||
while ( isdigit(ch) ) {
|
||||
value *= 10;
|
||||
value += ch - '0';
|
||||
ch = byte_getc(src);
|
||||
}
|
||||
item = vpi_scan(argv);
|
||||
assert(item);
|
||||
|
||||
val.format = vpiIntVal;
|
||||
val.value.integer = value;
|
||||
vpi_put_value(item, &val, 0, vpiNoDelay);
|
||||
rc += 1;
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
case 'x':
|
||||
/* Hex integer */
|
||||
tmp = malloc(2);
|
||||
value = 0;
|
||||
tmp[0] = 0;
|
||||
|
||||
ch = byte_getc(src);
|
||||
while (strchr("0123456789abcdefABCDEFxXzZ?_", ch)) {
|
||||
if (ch == '?')
|
||||
ch = 'x';
|
||||
if (ch != '_') {
|
||||
ch = tolower(ch);
|
||||
tmp[value++] = ch;
|
||||
tmp = realloc(tmp, value+1);
|
||||
tmp[value] = 0;
|
||||
}
|
||||
ch = byte_getc(src);
|
||||
}
|
||||
byte_ungetc(src, ch);
|
||||
|
||||
item = vpi_scan(argv);
|
||||
assert(item);
|
||||
|
||||
val.format = vpiHexStrVal;
|
||||
val.value.str = tmp;
|
||||
vpi_put_value(item, &val, 0, vpiNoDelay);
|
||||
free(tmp);
|
||||
rc += 1;
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
/* binary integer */
|
||||
tmp = malloc(2);
|
||||
value = 0;
|
||||
tmp[0] = 0;
|
||||
|
||||
ch = byte_getc(src);
|
||||
while (strchr("01234567xXzZ?_", ch)) {
|
||||
if (ch == '?')
|
||||
ch = 'x';
|
||||
if (ch != '_') {
|
||||
ch = tolower(ch);
|
||||
tmp[value++] = ch;
|
||||
tmp = realloc(tmp, value+1);
|
||||
tmp[value] = 0;
|
||||
}
|
||||
ch = byte_getc(src);
|
||||
}
|
||||
byte_ungetc(src, ch);
|
||||
|
||||
item = vpi_scan(argv);
|
||||
assert(item);
|
||||
|
||||
val.format = vpiOctStrVal;
|
||||
val.value.str = tmp;
|
||||
vpi_put_value(item, &val, 0, vpiNoDelay);
|
||||
free(tmp);
|
||||
rc += 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
vpi_printf("$scanf: Unknown format code: %c\n", code);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(fmt);
|
||||
|
||||
vpi_free_object(argv);
|
||||
|
||||
val.format = vpiIntVal;
|
||||
val.value.integer = rc;
|
||||
vpi_put_value(sys, &val, 0, vpiNoDelay);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sys_fscanf_compiletf(char*name)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sys_fscanf_calltf(char*name)
|
||||
{
|
||||
s_vpi_value val;
|
||||
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
|
||||
vpiHandle argv = vpi_iterate(vpiArgument, sys);
|
||||
vpiHandle item;
|
||||
|
||||
struct byte_source src;
|
||||
FILE*fd;
|
||||
|
||||
item = vpi_scan(argv);
|
||||
assert(item);
|
||||
|
||||
val.format = vpiIntVal;
|
||||
vpi_get_value(item, &val);
|
||||
|
||||
fd = vpi_get_file(val.value.integer);
|
||||
assert(fd);
|
||||
|
||||
src.str = 0;
|
||||
src.fd = fd;
|
||||
scan_format(sys, &src, argv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sys_sscanf_compiletf(char*name)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sys_sscanf_calltf(char*name)
|
||||
{
|
||||
s_vpi_value val;
|
||||
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
|
||||
vpiHandle argv = vpi_iterate(vpiArgument, sys);
|
||||
vpiHandle item;
|
||||
|
||||
struct byte_source src;
|
||||
char*str;
|
||||
|
||||
item = vpi_scan(argv);
|
||||
assert(item);
|
||||
|
||||
val.format = vpiStringVal;
|
||||
vpi_get_value(item, &val);
|
||||
str = strdup(val.value.str);
|
||||
|
||||
src.str = str;
|
||||
src.fd = 0;
|
||||
scan_format(sys, &src, argv);
|
||||
|
||||
free(str);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* All the Xscanf functions return a 32bit value.
|
||||
*/
|
||||
static int sys_fscanf_sizetf(char*x)
|
||||
{
|
||||
return 32;
|
||||
}
|
||||
|
||||
void sys_scanf_register()
|
||||
{
|
||||
s_vpi_systf_data tf_data;
|
||||
|
||||
//============================== fscanf
|
||||
tf_data.type = vpiSysFunc;
|
||||
tf_data.tfname = "$fscanf";
|
||||
tf_data.calltf = sys_fscanf_calltf;
|
||||
tf_data.compiletf = sys_fscanf_compiletf;
|
||||
tf_data.sizetf = sys_fscanf_sizetf;
|
||||
tf_data.user_data = "$fscanf";
|
||||
vpi_register_systf(&tf_data);
|
||||
|
||||
//============================== sscanf
|
||||
tf_data.type = vpiSysFunc;
|
||||
tf_data.tfname = "$sscanf";
|
||||
tf_data.calltf = sys_sscanf_calltf;
|
||||
tf_data.compiletf = sys_sscanf_compiletf;
|
||||
tf_data.sizetf = sys_fscanf_sizetf;
|
||||
tf_data.user_data = "$sscanf";
|
||||
vpi_register_systf(&tf_data);
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log $
|
||||
*/
|
||||
+6
-1
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: sys_table.c,v 1.25 2004/06/09 22:14:10 steve Exp $"
|
||||
#ident "$Id: sys_table.c,v 1.26 2006/08/03 05:06:04 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vpi_config.h"
|
||||
@@ -35,6 +35,7 @@ extern void sys_plusargs_register();
|
||||
extern void sys_random_register();
|
||||
extern void sys_random_mti_register();
|
||||
extern void sys_readmem_register();
|
||||
extern void sys_scanf_register();
|
||||
extern void sys_time_register();
|
||||
extern void sys_vcd_register();
|
||||
extern void sys_vcdoff_register();
|
||||
@@ -150,6 +151,7 @@ void (*vlog_startup_routines[])() = {
|
||||
sys_random_register,
|
||||
sys_random_mti_register,
|
||||
sys_readmem_register,
|
||||
sys_scanf_register,
|
||||
sys_time_register,
|
||||
sys_lxt_or_vcd_register,
|
||||
0
|
||||
@@ -158,6 +160,9 @@ void (*vlog_startup_routines[])() = {
|
||||
|
||||
/*
|
||||
* $Log: sys_table.c,v $
|
||||
* Revision 1.26 2006/08/03 05:06:04 steve
|
||||
* Add the scanf functions.
|
||||
*
|
||||
* Revision 1.25 2004/06/09 22:14:10 steve
|
||||
* Move Mersenne Twister to $mti_random, and make
|
||||
* the standard $random standard. Also, add $dist_poisson.
|
||||
|
||||
+2
-2
@@ -16,7 +16,7 @@
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.69 2005/06/12 01:42:20 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.70 2006/06/18 04:15:50 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
@@ -82,7 +82,7 @@ vpi_memory.o vpi_vthr_vector.o vpip_bin.o vpip_hex.o vpip_oct.o \
|
||||
vpip_to_dec.o vpip_format.o vvp_vpi.o
|
||||
|
||||
O = main.o parse.o parse_misc.o lexor.o arith.o bufif.o compile.o concat.o \
|
||||
dff.o extend.o npmos.o part.o reduce.o resolv.o stop.o symbols.o \
|
||||
dff.o extend.o npmos.o part.o reduce.o resolv.o sfunc.o stop.o symbols.o \
|
||||
ufunc.o codes.o \
|
||||
vthread.o schedule.o statistics.o tables.o udp.o vvp_net.o memory.o \
|
||||
event.o logic.o delay.o words.o $V
|
||||
|
||||
+11
-4
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: arith.cc,v 1.48 2006/01/03 06:19:31 steve Exp $"
|
||||
#ident "$Id: arith.cc,v 1.49 2006/07/30 02:51:36 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "arith.h"
|
||||
@@ -693,8 +693,8 @@ void vvp_shiftl::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
||||
vvp_send_vec4(ptr.ptr()->out, out);
|
||||
}
|
||||
|
||||
vvp_shiftr::vvp_shiftr(unsigned wid)
|
||||
: vvp_arith_(wid)
|
||||
vvp_shiftr::vvp_shiftr(unsigned wid, bool signed_flag)
|
||||
: vvp_arith_(wid), signed_flag_(signed_flag)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -720,8 +720,12 @@ void vvp_shiftr::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit)
|
||||
for (unsigned idx = shift ; idx < out.size() ; idx += 1)
|
||||
out.set_bit(idx-shift, op_a_.value(idx));
|
||||
|
||||
vvp_bit4_t pad = BIT4_0;
|
||||
if (signed_flag_ && op_a_.size() > 0)
|
||||
pad = op_a_.value(op_a_.size()-1);
|
||||
|
||||
for (unsigned idx = 0 ; idx < shift ; idx += 1)
|
||||
out.set_bit(idx+out.size()-shift, BIT4_0);
|
||||
out.set_bit(idx+out.size()-shift, pad);
|
||||
|
||||
vvp_send_vec4(ptr.ptr()->out, out);
|
||||
}
|
||||
@@ -780,6 +784,9 @@ void vvp_arith_sub_real::recv_real(vvp_net_ptr_t ptr, double bit)
|
||||
|
||||
/*
|
||||
* $Log: arith.cc,v $
|
||||
* Revision 1.49 2006/07/30 02:51:36 steve
|
||||
* Fix/implement signed right shift.
|
||||
*
|
||||
* Revision 1.48 2006/01/03 06:19:31 steve
|
||||
* Support wide divide nodes.
|
||||
*
|
||||
|
||||
+8
-2
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: arith.h,v 1.33 2006/01/03 06:19:31 steve Exp $"
|
||||
#ident "$Id: arith.h,v 1.34 2006/07/30 02:51:36 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vvp_net.h"
|
||||
@@ -191,9 +191,12 @@ class vvp_shiftl : public vvp_arith_ {
|
||||
class vvp_shiftr : public vvp_arith_ {
|
||||
|
||||
public:
|
||||
explicit vvp_shiftr(unsigned wid);
|
||||
explicit vvp_shiftr(unsigned wid, bool signed_flag);
|
||||
~vvp_shiftr();
|
||||
virtual void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
|
||||
|
||||
private:
|
||||
bool signed_flag_;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -233,6 +236,9 @@ class vvp_arith_sub_real : public vvp_arith_real_ {
|
||||
|
||||
/*
|
||||
* $Log: arith.h,v $
|
||||
* Revision 1.34 2006/07/30 02:51:36 steve
|
||||
* Fix/implement signed right shift.
|
||||
*
|
||||
* Revision 1.33 2006/01/03 06:19:31 steve
|
||||
* Support wide divide nodes.
|
||||
*
|
||||
|
||||
+5
-1
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: codes.h,v 1.78 2006/02/02 02:44:00 steve Exp $"
|
||||
#ident "$Id: codes.h,v 1.79 2006/08/09 05:19:08 steve Exp $"
|
||||
#endif
|
||||
|
||||
|
||||
@@ -95,6 +95,7 @@ extern bool of_LOAD_XP(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_LOADI_WR(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_MOD(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_MOD_S(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_MOD_WR(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_MOV(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_MUL(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_MUL_WR(vthread_t thr, vvp_code_t code);
|
||||
@@ -178,6 +179,9 @@ extern vvp_code_t codespace_null(void);
|
||||
|
||||
/*
|
||||
* $Log: codes.h,v $
|
||||
* Revision 1.79 2006/08/09 05:19:08 steve
|
||||
* Add support for real valued modulus.
|
||||
*
|
||||
* Revision 1.78 2006/02/02 02:44:00 steve
|
||||
* Allow part selects of memory words in l-values.
|
||||
*
|
||||
|
||||
+20
-6
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: compile.cc,v 1.219 2006/03/18 22:51:10 steve Exp $"
|
||||
#ident "$Id: compile.cc,v 1.223 2006/08/09 05:19:08 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "arith.h"
|
||||
@@ -109,7 +109,7 @@ const static struct opcode_table_s opcode_table[] = {
|
||||
{ "%cvt/ri", of_CVT_RI, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
|
||||
{ "%cvt/vr", of_CVT_VR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%deassign",of_DEASSIGN,1,{OA_FUNC_PTR, OA_NONE, OA_NONE} },
|
||||
{ "%delay", of_DELAY, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
||||
{ "%delay", of_DELAY, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
|
||||
{ "%delayx", of_DELAYX, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
||||
{ "%div", of_DIV, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%div/s", of_DIV_S, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
@@ -139,6 +139,7 @@ const static struct opcode_table_s opcode_table[] = {
|
||||
{ "%loadi/wr",of_LOADI_WR,3,{OA_BIT1, OA_NUMBER, OA_BIT2} },
|
||||
{ "%mod", of_MOD, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%mod/s", of_MOD_S, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%mod/wr", of_MOD_WR, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
|
||||
{ "%mov", of_MOV, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%mul", of_MUL, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%mul/wr", of_MUL_WR, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
|
||||
@@ -1060,11 +1061,12 @@ void compile_shiftl(char*label, long wid, unsigned argc, struct symb_s*argv)
|
||||
make_arith(arith, label, argc, argv);
|
||||
}
|
||||
|
||||
void compile_shiftr(char*label, long wid, unsigned argc, struct symb_s*argv)
|
||||
void compile_shiftr(char*label, long wid, bool signed_flag,
|
||||
unsigned argc, struct symb_s*argv)
|
||||
{
|
||||
assert( wid > 0 );
|
||||
|
||||
vvp_arith_ *arith = new vvp_shiftr(wid);
|
||||
vvp_arith_ *arith = new vvp_shiftr(wid, signed_flag);
|
||||
make_arith(arith, label, argc, argv);
|
||||
}
|
||||
|
||||
@@ -1417,7 +1419,7 @@ void compile_vpi_call(char*label, char*name, unsigned argc, vpiHandle*argv)
|
||||
|
||||
/* Create a vpiHandle that bundles the call information, and
|
||||
store that handle in the instruction. */
|
||||
code->handle = vpip_build_vpi_call(name, 0, 0, argc, argv);
|
||||
code->handle = vpip_build_vpi_call(name, 0, 0, 0, argc, argv);
|
||||
if (code->handle == 0)
|
||||
compile_errors += 1;
|
||||
|
||||
@@ -1438,7 +1440,7 @@ void compile_vpi_func_call(char*label, char*name,
|
||||
|
||||
/* Create a vpiHandle that bundles the call information, and
|
||||
store that handle in the instruction. */
|
||||
code->handle = vpip_build_vpi_call(name, vbit, vwid, argc, argv);
|
||||
code->handle = vpip_build_vpi_call(name, vbit, vwid, 0, argc, argv);
|
||||
if (code->handle == 0)
|
||||
compile_errors += 1;
|
||||
|
||||
@@ -1495,6 +1497,18 @@ void compile_param_string(char*label, char*name, char*value)
|
||||
|
||||
/*
|
||||
* $Log: compile.cc,v $
|
||||
* Revision 1.223 2006/08/09 05:19:08 steve
|
||||
* Add support for real valued modulus.
|
||||
*
|
||||
* Revision 1.222 2006/08/08 05:11:37 steve
|
||||
* Handle 64bit delay constants.
|
||||
*
|
||||
* Revision 1.221 2006/07/30 02:51:36 steve
|
||||
* Fix/implement signed right shift.
|
||||
*
|
||||
* Revision 1.220 2006/06/18 04:15:50 steve
|
||||
* Add support for system functions in continuous assignments.
|
||||
*
|
||||
* Revision 1.219 2006/03/18 22:51:10 steve
|
||||
* Syntax for carrying sign with parameter.
|
||||
*
|
||||
|
||||
+10
-2
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: compile.h,v 1.80 2006/03/18 22:51:10 steve Exp $"
|
||||
#ident "$Id: compile.h,v 1.82 2006/07/30 02:51:36 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <stdio.h>
|
||||
@@ -169,12 +169,14 @@ extern void compile_reduce_xnor(char*label, struct symb_s arg);
|
||||
|
||||
extern void compile_extend_signed(char*label, long width, struct symb_s arg);
|
||||
|
||||
extern void compile_sfunc(char*label, char*name, char*format_string,
|
||||
unsigned argc, struct symb_s*argv);
|
||||
extern void compile_repeat(char*label, long width, long repeat,
|
||||
struct symb_s arg);
|
||||
|
||||
extern void compile_shiftl(char*label, long width,
|
||||
unsigned argc, struct symb_s*argv);
|
||||
extern void compile_shiftr(char*label, long width,
|
||||
extern void compile_shiftr(char*label, long width, bool signed_flag,
|
||||
unsigned argc, struct symb_s*argv);
|
||||
|
||||
extern void compile_timescale(long units);
|
||||
@@ -343,6 +345,12 @@ extern void compile_alias_real(char*label, char*name,
|
||||
|
||||
/*
|
||||
* $Log: compile.h,v $
|
||||
* Revision 1.82 2006/07/30 02:51:36 steve
|
||||
* Fix/implement signed right shift.
|
||||
*
|
||||
* Revision 1.81 2006/06/18 04:15:50 steve
|
||||
* Add support for system functions in continuous assignments.
|
||||
*
|
||||
* Revision 1.80 2006/03/18 22:51:10 steve
|
||||
* Syntax for carrying sign with parameter.
|
||||
*
|
||||
|
||||
+19
-1
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: config.h.in,v 1.20 2005/09/14 02:50:07 steve Exp $"
|
||||
#ident "$Id: config.h.in,v 1.22 2006/04/27 05:04:59 steve Exp $"
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus)
|
||||
@@ -48,6 +48,8 @@
|
||||
# undef HAVE_LIBREADLINE
|
||||
# undef HAVE_READLINE_READLINE_H
|
||||
# undef HAVE_READLINE_HISTORY_H
|
||||
# undef HAVE_STDINT_H
|
||||
# undef HAVE_LROUND
|
||||
|
||||
/* Figure if I can use readline. */
|
||||
#undef USE_READLINE
|
||||
@@ -61,7 +63,9 @@
|
||||
# define MODULE_DIR "."
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STDINT_H
|
||||
# include <stdint.h>
|
||||
#endif
|
||||
|
||||
#if SIZEOF_UNSIGNED >= 8
|
||||
typedef unsigned vvp_time64_t;
|
||||
@@ -86,6 +90,14 @@ typedef unsigned long vvp_time64_t;
|
||||
# undef HAVE_SYS_RESOURCE_H
|
||||
# undef LINUX
|
||||
|
||||
#if !defined(HAVE_LROUND)
|
||||
#if defined(__cplusplus)
|
||||
extern "C" long lround(double x);
|
||||
#else
|
||||
extern long lround(double x);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* When doing dynamic linking, we need a uniform way to identify the
|
||||
@@ -107,6 +119,12 @@ typedef unsigned long vvp_time64_t;
|
||||
|
||||
/*
|
||||
* $Log: config.h.in,v $
|
||||
* Revision 1.22 2006/04/27 05:04:59 steve
|
||||
* Detect missing lround function.
|
||||
*
|
||||
* Revision 1.21 2006/04/25 22:41:10 steve
|
||||
* Detect the presence of stdint.h
|
||||
*
|
||||
* Revision 1.20 2005/09/14 02:50:07 steve
|
||||
* Add word integer compares.
|
||||
*
|
||||
|
||||
+5
-1
@@ -35,7 +35,7 @@ fi
|
||||
AC_PROG_INSTALL
|
||||
|
||||
AC_LANG_CPLUSPLUS
|
||||
AC_CHECK_HEADERS(getopt.h malloc.h iosfwd)
|
||||
AC_CHECK_HEADERS(getopt.h malloc.h stdint.h iosfwd)
|
||||
|
||||
AC_CHECK_SIZEOF(unsigned long long)
|
||||
AC_CHECK_SIZEOF(unsigned long)
|
||||
@@ -73,6 +73,10 @@ case "${host}" in
|
||||
;;
|
||||
esac
|
||||
|
||||
# Check that these functions exist. They are mostly C99
|
||||
# functions that older compilers may not yet support.
|
||||
AC_CHECK_FUNCS(lround)
|
||||
|
||||
# see how we can give some resource usage stats with -v
|
||||
# Linux does not provide mem stats in rusage, use /proc/self/statm.
|
||||
|
||||
|
||||
+25
-1
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: delay.cc,v 1.12 2006/01/02 05:32:07 steve Exp $"
|
||||
#ident "$Id: delay.cc,v 1.13 2006/07/08 21:48:00 steve Exp $"
|
||||
#endif
|
||||
|
||||
#include "delay.h"
|
||||
@@ -220,6 +220,27 @@ void vvp_fun_delay::recv_vec8(vvp_net_ptr_t port, vvp_vector8_t bit)
|
||||
|
||||
void vvp_fun_delay::recv_real(vvp_net_ptr_t port, double bit)
|
||||
{
|
||||
if (port.port() > 0) {
|
||||
/* If the port is not 0, then this is a delay value that
|
||||
should be rounded and converted to an integer delay. */
|
||||
unsigned long long val = 0;
|
||||
if (bit > 0)
|
||||
val = (unsigned long long) (bit+0.5);
|
||||
|
||||
switch (port.port()) {
|
||||
case 1:
|
||||
delay_.set_rise(val);
|
||||
return;
|
||||
case 2:
|
||||
delay_.set_fall(val);
|
||||
return;
|
||||
case 3:
|
||||
delay_.set_decay(val);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (cur_real_ == bit)
|
||||
return;
|
||||
|
||||
@@ -258,6 +279,9 @@ void vvp_fun_delay::run_run_real_()
|
||||
|
||||
/*
|
||||
* $Log: delay.cc,v $
|
||||
* Revision 1.13 2006/07/08 21:48:00 steve
|
||||
* Delay object supports real valued delays.
|
||||
*
|
||||
* Revision 1.12 2006/01/02 05:32:07 steve
|
||||
* Require explicit delay node from source.
|
||||
*
|
||||
|
||||
+14
-1
@@ -1,4 +1,6 @@
|
||||
|
||||
%option never-interactive
|
||||
|
||||
%{
|
||||
/*
|
||||
* Copyright (c) 2001-2005 Stephen Williams ([email protected])
|
||||
@@ -19,7 +21,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: lexor.lex,v 1.59 2006/03/08 05:29:42 steve Exp $"
|
||||
#ident "$Id: lexor.lex,v 1.62 2006/07/30 02:51:36 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "parse_misc.h"
|
||||
@@ -128,8 +130,10 @@
|
||||
".repeat" { return K_REPEAT; }
|
||||
".resolv" { return K_RESOLV; }
|
||||
".scope" { return K_SCOPE; }
|
||||
".sfunc" { return K_SFUNC; }
|
||||
".shift/l" { return K_SHIFTL; }
|
||||
".shift/r" { return K_SHIFTR; }
|
||||
".shift/rs" { return K_SHIFTRS; }
|
||||
".thread" { return K_THREAD; }
|
||||
".timescale" { return K_TIMESCALE; }
|
||||
".ufunc" { return K_UFUNC; }
|
||||
@@ -206,6 +210,15 @@ int yywrap()
|
||||
|
||||
/*
|
||||
* $Log: lexor.lex,v $
|
||||
* Revision 1.62 2006/07/30 02:51:36 steve
|
||||
* Fix/implement signed right shift.
|
||||
*
|
||||
* Revision 1.61 2006/06/18 04:15:50 steve
|
||||
* Add support for system functions in continuous assignments.
|
||||
*
|
||||
* Revision 1.60 2006/05/17 04:15:25 steve
|
||||
* Lexor os never interactive.
|
||||
*
|
||||
* Revision 1.59 2006/03/08 05:29:42 steve
|
||||
* Add support for logic parameters.
|
||||
*
|
||||
|
||||
+26
-1
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: main.cc,v 1.40 2005/01/29 06:28:19 steve Exp $"
|
||||
#ident "$Id: main.cc,v 1.43 2006/04/28 15:44:37 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -53,6 +53,22 @@ extern "C" int optind;
|
||||
extern "C" const char*optarg;
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_LROUND)
|
||||
/*
|
||||
* If the system doesn't provide the lround function, then we provide
|
||||
* it ourselves here. It is simply the nearest integer, rounded away
|
||||
* from zero.
|
||||
*/
|
||||
# include <math.h>
|
||||
extern "C" long int lround(double x)
|
||||
{
|
||||
if (x >= 0.0)
|
||||
return (long)floor(x+0.5);
|
||||
else
|
||||
return (long)ceil(x-0.5);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool verbose_flag = false;
|
||||
|
||||
static char log_buffer[4096];
|
||||
@@ -281,6 +297,15 @@ int main(int argc, char*argv[])
|
||||
|
||||
/*
|
||||
* $Log: main.cc,v $
|
||||
* Revision 1.43 2006/04/28 15:44:37 steve
|
||||
* Include math.h with lround implementation.
|
||||
*
|
||||
* Revision 1.42 2006/04/28 15:40:30 steve
|
||||
* lround takes double, not float.
|
||||
*
|
||||
* Revision 1.41 2006/04/27 05:04:59 steve
|
||||
* Detect missing lround function.
|
||||
*
|
||||
* Revision 1.40 2005/01/29 06:28:19 steve
|
||||
* Add the -s flag to start up interactive.
|
||||
*
|
||||
|
||||
+5
-1
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Copyright (c) 2001-2003 Stephen Williams ([email protected])
|
||||
*
|
||||
* $Id: opcodes.txt,v 1.70 2006/02/02 02:44:00 steve Exp $
|
||||
* $Id: opcodes.txt,v 1.71 2006/08/09 05:19:08 steve Exp $
|
||||
*/
|
||||
|
||||
|
||||
@@ -424,6 +424,10 @@ replaced with the result.
|
||||
|
||||
The /s form does signed %.
|
||||
|
||||
* %mod/wr <bit-l>, <bit-r>
|
||||
|
||||
This opcode is the real-valued modulus of the two real values.
|
||||
|
||||
* %mov <dst>, <src>, <wid>
|
||||
|
||||
This instruction copies a vector from one place in register space to
|
||||
|
||||
+20
-3
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: parse.y,v 1.82 2006/03/18 22:51:10 steve Exp $"
|
||||
#ident "$Id: parse.y,v 1.84 2006/07/30 02:51:36 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "parse_misc.h"
|
||||
@@ -67,7 +67,8 @@ extern FILE*yyin;
|
||||
%token K_PARAM_STR K_PARAM_L K_PART K_PART_PV
|
||||
%token K_PART_V K_REDUCE_AND K_REDUCE_OR K_REDUCE_XOR
|
||||
%token K_REDUCE_NAND K_REDUCE_NOR K_REDUCE_XNOR K_REPEAT
|
||||
%token K_RESOLV K_SCOPE K_SHIFTL K_SHIFTR K_THREAD K_TIMESCALE K_UFUNC
|
||||
%token K_RESOLV K_SCOPE K_SFUNC K_SHIFTL K_SHIFTR K_SHIFTRS
|
||||
%token K_THREAD K_TIMESCALE K_UFUNC
|
||||
%token K_UDP K_UDP_C K_UDP_S
|
||||
%token K_MEM K_MEM_P K_MEM_I
|
||||
%token K_VAR K_VAR_S K_VAR_I K_VAR_R K_vpi_call K_vpi_func K_vpi_func_r
|
||||
@@ -329,6 +330,10 @@ statement
|
||||
| T_LABEL K_EXTEND_S T_NUMBER ',' symbol ';'
|
||||
{ compile_extend_signed($1, $3, $5); }
|
||||
|
||||
/* System function call */
|
||||
| T_LABEL K_SFUNC T_STRING ',' T_STRING ',' symbols ';'
|
||||
{ compile_sfunc($1, $3, $5, $7.cnt, $7.vect); }
|
||||
|
||||
/* Shift nodes. */
|
||||
|
||||
| T_LABEL K_SHIFTL T_NUMBER ',' symbols ';'
|
||||
@@ -338,7 +343,13 @@ statement
|
||||
|
||||
| T_LABEL K_SHIFTR T_NUMBER ',' symbols ';'
|
||||
{ struct symbv_s obj = $5;
|
||||
compile_shiftr($1, $3, obj.cnt, obj.vect);
|
||||
compile_shiftr($1, $3, false, obj.cnt, obj.vect);
|
||||
}
|
||||
|
||||
|
||||
| T_LABEL K_SHIFTRS T_NUMBER ',' symbols ';'
|
||||
{ struct symbv_s obj = $5;
|
||||
compile_shiftr($1, $3, true, obj.cnt, obj.vect);
|
||||
}
|
||||
|
||||
|
||||
@@ -739,6 +750,12 @@ int compile_design(const char*path)
|
||||
|
||||
/*
|
||||
* $Log: parse.y,v $
|
||||
* Revision 1.84 2006/07/30 02:51:36 steve
|
||||
* Fix/implement signed right shift.
|
||||
*
|
||||
* Revision 1.83 2006/06/18 04:15:50 steve
|
||||
* Add support for system functions in continuous assignments.
|
||||
*
|
||||
* Revision 1.82 2006/03/18 22:51:10 steve
|
||||
* Syntax for carrying sign with parameter.
|
||||
*
|
||||
|
||||
+9
-6
@@ -16,7 +16,7 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ident "$Id: part.cc,v 1.9 2005/09/20 00:51:53 steve Exp $"
|
||||
#ident "$Id: part.cc,v 1.11 2006/05/01 18:44:08 steve Exp $"
|
||||
|
||||
# include "compile.h"
|
||||
# include "part.h"
|
||||
@@ -58,13 +58,10 @@ void vvp_fun_part::run_run()
|
||||
vvp_net_t*ptr = net_;
|
||||
net_ = 0;
|
||||
|
||||
vvp_vector4_t res (wid_);
|
||||
vvp_vector4_t res (wid_, BIT4_X);
|
||||
for (unsigned idx = 0 ; idx < wid_ ; idx += 1) {
|
||||
if (idx + base_ < val_.size())
|
||||
res.set_bit(idx, val_.value(base_+idx));
|
||||
else
|
||||
|
||||
res.set_bit(idx, BIT4_X);
|
||||
}
|
||||
vvp_send_vec4(ptr->out, res);
|
||||
}
|
||||
@@ -85,7 +82,7 @@ void vvp_fun_part_pv::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
||||
if (bit.size() != wid_) {
|
||||
cerr << "internal error: part_pv data mismatch. "
|
||||
<< "base_=" << base_ << ", wid_=" << wid_
|
||||
<< ", vwid_=" << vwid_ << ", bit=" // XXX << bit
|
||||
<< ", vwid_=" << vwid_ << ", bit=" << bit
|
||||
<< endl;
|
||||
}
|
||||
assert(bit.size() == wid_);
|
||||
@@ -183,6 +180,12 @@ void compile_part_select_var(char*label, char*source, char*var,
|
||||
|
||||
/*
|
||||
* $Log: part.cc,v $
|
||||
* Revision 1.11 2006/05/01 18:44:08 steve
|
||||
* Reduce steps to make logic output.
|
||||
*
|
||||
* Revision 1.10 2006/04/26 04:39:23 steve
|
||||
* Include bit value in assertion message.
|
||||
*
|
||||
* Revision 1.9 2005/09/20 00:51:53 steve
|
||||
* Lazy processing of vvp_fun_part functor.
|
||||
*
|
||||
|
||||
+13
-13
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: reduce.cc,v 1.2 2005/06/22 00:04:49 steve Exp $"
|
||||
#ident "$Id: reduce.cc,v 1.4 2006/05/01 20:47:03 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "compile.h"
|
||||
@@ -53,8 +53,7 @@ void vvp_reduce_and::recv_vec4(vvp_net_ptr_t prt, const vvp_vector4_t&bit)
|
||||
for (unsigned idx = 0 ; idx < bit.size() ; idx += 1)
|
||||
res = res & bit.value(idx);
|
||||
|
||||
vvp_vector4_t rv (1);
|
||||
rv.set_bit(0, res);
|
||||
vvp_vector4_t rv (1, res);
|
||||
vvp_send_vec4(prt.ptr()->out, rv);
|
||||
}
|
||||
|
||||
@@ -81,8 +80,7 @@ void vvp_reduce_or::recv_vec4(vvp_net_ptr_t prt, const vvp_vector4_t&bit)
|
||||
for (unsigned idx = 0 ; idx < bit.size() ; idx += 1)
|
||||
res = res | bit.value(idx);
|
||||
|
||||
vvp_vector4_t rv (1);
|
||||
rv.set_bit(0, res);
|
||||
vvp_vector4_t rv (1, res);
|
||||
vvp_send_vec4(prt.ptr()->out, rv);
|
||||
}
|
||||
|
||||
@@ -109,8 +107,7 @@ void vvp_reduce_xor::recv_vec4(vvp_net_ptr_t prt, const vvp_vector4_t&bit)
|
||||
for (unsigned idx = 0 ; idx < bit.size() ; idx += 1)
|
||||
res = res ^ bit.value(idx);
|
||||
|
||||
vvp_vector4_t rv (1);
|
||||
rv.set_bit(0, res);
|
||||
vvp_vector4_t rv (1, res);
|
||||
vvp_send_vec4(prt.ptr()->out, rv);
|
||||
}
|
||||
|
||||
@@ -137,8 +134,7 @@ void vvp_reduce_nand::recv_vec4(vvp_net_ptr_t prt, const vvp_vector4_t&bit)
|
||||
for (unsigned idx = 0 ; idx < bit.size() ; idx += 1)
|
||||
res = res & bit.value(idx);
|
||||
|
||||
vvp_vector4_t rv (1);
|
||||
rv.set_bit(0, ~res);
|
||||
vvp_vector4_t rv (1, ~res);
|
||||
vvp_send_vec4(prt.ptr()->out, rv);
|
||||
}
|
||||
|
||||
@@ -165,8 +161,7 @@ void vvp_reduce_nor::recv_vec4(vvp_net_ptr_t prt, const vvp_vector4_t&bit)
|
||||
for (unsigned idx = 0 ; idx < bit.size() ; idx += 1)
|
||||
res = res | bit.value(idx);
|
||||
|
||||
vvp_vector4_t rv (1);
|
||||
rv.set_bit(0, ~res);
|
||||
vvp_vector4_t rv (1, ~res);
|
||||
vvp_send_vec4(prt.ptr()->out, rv);
|
||||
}
|
||||
|
||||
@@ -193,8 +188,7 @@ void vvp_reduce_xnor::recv_vec4(vvp_net_ptr_t prt, const vvp_vector4_t&bit)
|
||||
for (unsigned idx = 0 ; idx < bit.size() ; idx += 1)
|
||||
res = res ^ bit.value(idx);
|
||||
|
||||
vvp_vector4_t rv (1);
|
||||
rv.set_bit(0, ~res);
|
||||
vvp_vector4_t rv (1, ~res);
|
||||
vvp_send_vec4(prt.ptr()->out, rv);
|
||||
}
|
||||
|
||||
@@ -247,6 +241,12 @@ void compile_reduce_xnor(char*label, struct symb_s arg)
|
||||
|
||||
/*
|
||||
* $Log: reduce.cc,v $
|
||||
* Revision 1.4 2006/05/01 20:47:03 steve
|
||||
* Forgot to invert nand output.
|
||||
*
|
||||
* Revision 1.3 2006/05/01 18:44:08 steve
|
||||
* Reduce steps to make logic output.
|
||||
*
|
||||
* Revision 1.2 2005/06/22 00:04:49 steve
|
||||
* Reduce vvp_vector4 copies by using const references.
|
||||
*
|
||||
|
||||
+5
-2
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: schedule.cc,v 1.41 2006/02/02 02:44:00 steve Exp $"
|
||||
#ident "$Id: schedule.cc,v 1.42 2006/08/06 18:17:00 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "schedule.h"
|
||||
@@ -293,7 +293,7 @@ static void schedule_event_(struct event_s*cur, vvp_time64_t delay,
|
||||
struct event_time_s*tmp = new struct event_time_s;
|
||||
tmp->active = 0;
|
||||
tmp->nbassign = 0;
|
||||
ctim->rosync = 0;
|
||||
tmp->rosync = 0;
|
||||
tmp->delay = delay;
|
||||
tmp->next = ctim;
|
||||
ctim->delay -= delay;
|
||||
@@ -608,6 +608,9 @@ void schedule_simulate(void)
|
||||
|
||||
/*
|
||||
* $Log: schedule.cc,v $
|
||||
* Revision 1.42 2006/08/06 18:17:00 steve
|
||||
* Fix typo in initialize of new event_time cell.
|
||||
*
|
||||
* Revision 1.41 2006/02/02 02:44:00 steve
|
||||
* Allow part selects of memory words in l-values.
|
||||
*
|
||||
|
||||
+160
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
* Copyright (c) 2006 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
|
||||
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: sfunc.cc,v 1.1 2006/06/18 04:15:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "compile.h"
|
||||
# include "sfunc.h"
|
||||
#ifdef HAVE_MALLOC_H
|
||||
# include <malloc.h>
|
||||
#endif
|
||||
# include <stdlib.h>
|
||||
# include <string.h>
|
||||
# include <iostream>
|
||||
# include <assert.h>
|
||||
|
||||
|
||||
sfunc_core::sfunc_core(vvp_net_t*net, vpiHandle sys,
|
||||
unsigned argc, vpiHandle*argv)
|
||||
: vvp_wide_fun_core(net, argc)
|
||||
{
|
||||
sys_ = sys;
|
||||
argc_ = argc;
|
||||
argv_ = argv;
|
||||
}
|
||||
|
||||
sfunc_core::~sfunc_core()
|
||||
{
|
||||
}
|
||||
|
||||
void sfunc_core::recv_vec4_from_inputs(unsigned port)
|
||||
{
|
||||
vpiHandle vpi = argv_[port];
|
||||
assert(vpi_get(vpiConstType,vpi) == vpiBinaryConst);
|
||||
|
||||
struct __vpiBinaryConst*obj
|
||||
= (struct __vpiBinaryConst*)vpi;
|
||||
|
||||
obj->bits = value(port);
|
||||
|
||||
invoke_function_();
|
||||
}
|
||||
|
||||
void sfunc_core::recv_real_from_inputs(unsigned port)
|
||||
{
|
||||
vpiHandle vpi = argv_[port];
|
||||
assert(vpi_get(vpiConstType,vpi) == vpiRealConst);
|
||||
|
||||
struct __vpiRealConst*obj
|
||||
= (struct __vpiRealConst*)vpi;
|
||||
|
||||
obj->value = value_r(port);
|
||||
|
||||
invoke_function_();
|
||||
}
|
||||
|
||||
void sfunc_core::invoke_function_()
|
||||
{
|
||||
vpip_execute_vpi_call(0, sys_);
|
||||
}
|
||||
|
||||
static int make_vpi_argv(unsigned argc, vpiHandle*vpi_argv,
|
||||
const char*arg_string)
|
||||
{
|
||||
unsigned idx = 0;
|
||||
const char*cp = arg_string;
|
||||
int return_type = 0;
|
||||
|
||||
switch (*cp) {
|
||||
case 'r': // real result
|
||||
cp += 1;
|
||||
return_type = -vpiRealConst;
|
||||
break;
|
||||
|
||||
case 'v': // vector4_t
|
||||
cp += 1;
|
||||
return_type = strtoul(cp, 0, 10);
|
||||
cp += strspn(cp, "0123456789");
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
while (*cp) {
|
||||
assert(idx < argc);
|
||||
|
||||
switch (*cp) {
|
||||
case 'r': // real
|
||||
cp += 1;
|
||||
vpi_argv[idx] = vpip_make_real_const(0.0);
|
||||
break;
|
||||
|
||||
case 'v': { // vector4_t (v<n>)
|
||||
cp += 1;
|
||||
unsigned wid = strtoul(cp, 0, 10);
|
||||
cp += strspn(cp, "0123456789");
|
||||
vpi_argv[idx] = vpip_make_binary_const(wid, "x");
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
idx += 1;
|
||||
}
|
||||
|
||||
assert(idx == argc);
|
||||
return return_type;
|
||||
}
|
||||
|
||||
|
||||
void compile_sfunc(char*label, char*name, char*format_string,
|
||||
unsigned argc, struct symb_s*argv)
|
||||
{
|
||||
vpiHandle*vpi_argv = new vpiHandle[argc];
|
||||
int width_code = make_vpi_argv(argc, vpi_argv, format_string);
|
||||
free(format_string);
|
||||
|
||||
vvp_net_t*ptr = new vvp_net_t;
|
||||
|
||||
vpiHandle sys = vpip_build_vpi_call(name, 0, width_code, ptr,
|
||||
argc, vpi_argv);
|
||||
assert(sys);
|
||||
|
||||
/* Create and connect the functor to the label. */
|
||||
sfunc_core*score = new sfunc_core(ptr, sys, argc, vpi_argv);
|
||||
ptr->fun = score;
|
||||
define_functor_symbol(label, ptr);
|
||||
free(label);
|
||||
|
||||
/* Link the inputs to the functor. */
|
||||
wide_inputs_connect(score, argc, argv);
|
||||
free(argv);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* $Log: sfunc.cc,v $
|
||||
* Revision 1.1 2006/06/18 04:15:50 steve
|
||||
* Add support for system functions in continuous assignments.
|
||||
*
|
||||
*/
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
#ifndef __sfunc_H
|
||||
#define __sfunc_H
|
||||
/*
|
||||
* Copyright (c) 2006 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
|
||||
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: sfunc.h,v 1.1 2006/06/18 04:15:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "pointers.h"
|
||||
|
||||
class sfunc_core : public vvp_wide_fun_core {
|
||||
|
||||
public:
|
||||
sfunc_core(vvp_net_t*ptr, vpiHandle sys, unsigned argc, vpiHandle*argv);
|
||||
~sfunc_core();
|
||||
|
||||
private:
|
||||
void recv_vec4_from_inputs(unsigned port);
|
||||
void recv_real_from_inputs(unsigned port);
|
||||
|
||||
void invoke_function_();
|
||||
|
||||
private:
|
||||
vpiHandle sys_;
|
||||
unsigned argc_;
|
||||
vpiHandle*argv_;
|
||||
};
|
||||
|
||||
/*
|
||||
* $Log: sfunc.h,v $
|
||||
* Revision 1.1 2006/06/18 04:15:50 steve
|
||||
* Add support for system functions in continuous assignments.
|
||||
*
|
||||
*/
|
||||
#endif
|
||||
+5
-2
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: stop.cc,v 1.15 2005/11/25 18:35:38 steve Exp $"
|
||||
#ident "$Id: stop.cc,v 1.16 2006/06/18 04:15:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -174,7 +174,7 @@ static void cmd_call(unsigned argc, char*argv[])
|
||||
vpi task and execute that call. Free the call structure
|
||||
when we finish. */
|
||||
if (errors == 0) {
|
||||
vpiHandle call_handle = vpip_build_vpi_call(argv[0], 0, 0,
|
||||
vpiHandle call_handle = vpip_build_vpi_call(argv[0], 0, 0, 0,
|
||||
vpi_argc, vpi_argv);
|
||||
if (call_handle == 0)
|
||||
goto out;
|
||||
@@ -505,6 +505,9 @@ void stop_handler(int rc)
|
||||
|
||||
/*
|
||||
* $Log: stop.cc,v $
|
||||
* Revision 1.16 2006/06/18 04:15:50 steve
|
||||
* Add support for system functions in continuous assignments.
|
||||
*
|
||||
* Revision 1.15 2005/11/25 18:35:38 steve
|
||||
* stop/continue messages go through MCD for logging.
|
||||
*
|
||||
|
||||
+26
-1
@@ -20,7 +20,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: udp.cc,v 1.33 2005/06/11 16:21:08 steve Exp $"
|
||||
#ident "$Id: udp.cc,v 1.34 2006/05/18 05:13:45 steve Exp $"
|
||||
#endif
|
||||
|
||||
#include "udp.h"
|
||||
@@ -44,6 +44,14 @@ struct vvp_udp_s *udp_find(const char *label)
|
||||
return (struct vvp_udp_s *)v.ptr;
|
||||
}
|
||||
|
||||
ostream& operator <<(ostream&o, const struct udp_levels_table&table)
|
||||
{
|
||||
o << "[" << hex << table.mask0
|
||||
<< "/" << hex << table.mask1
|
||||
<< "/" << hex << table.maskx << "]";
|
||||
return o;
|
||||
}
|
||||
|
||||
vvp_udp_s::vvp_udp_s(char*label, unsigned ports, vvp_bit4_t init)
|
||||
: ports_(ports), init_(init)
|
||||
{
|
||||
@@ -607,10 +615,24 @@ void vvp_udp_seq_s::compile_table(char**tab)
|
||||
|
||||
}
|
||||
|
||||
bool operator == (const udp_levels_table&a, const udp_levels_table&b)
|
||||
{
|
||||
if (a.mask0 != b.mask0)
|
||||
return false;
|
||||
if (a.mask1 != b.mask1)
|
||||
return false;
|
||||
if (a.maskx != b.maskx)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
vvp_bit4_t vvp_udp_seq_s::calculate_output(const udp_levels_table&cur,
|
||||
const udp_levels_table&prev,
|
||||
vvp_bit4_t cur_out)
|
||||
{
|
||||
if (cur == prev)
|
||||
return cur_out;
|
||||
|
||||
udp_levels_table cur_tmp = cur;
|
||||
|
||||
unsigned long mask_out = 1UL << port_count();
|
||||
@@ -924,6 +946,9 @@ void compile_udp_functor(char*label, char*type,
|
||||
|
||||
/*
|
||||
* $Log: udp.cc,v $
|
||||
* Revision 1.34 2006/05/18 05:13:45 steve
|
||||
* Synchronous primitives only follow edges.
|
||||
*
|
||||
* Revision 1.33 2005/06/11 16:21:08 steve
|
||||
* UD delays use delay node.
|
||||
*
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: udp.h,v 1.19 2005/06/11 16:21:08 steve Exp $"
|
||||
#ident "$Id: udp.h,v 1.20 2006/05/18 05:13:45 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <vvp_net.h>
|
||||
@@ -108,6 +108,7 @@ struct udp_levels_table {
|
||||
unsigned long mask1;
|
||||
unsigned long maskx;
|
||||
};
|
||||
extern ostream& operator<< (ostream&o, const struct udp_levels_table&t);
|
||||
|
||||
class vvp_udp_comb_s : public vvp_udp_s {
|
||||
|
||||
@@ -245,6 +246,9 @@ class vvp_udp_fun_core : public vvp_wide_fun_core, private vvp_gen_event_s {
|
||||
|
||||
/*
|
||||
* $Log: udp.h,v $
|
||||
* Revision 1.20 2006/05/18 05:13:45 steve
|
||||
* Synchronous primitives only follow edges.
|
||||
*
|
||||
* Revision 1.19 2005/06/11 16:21:08 steve
|
||||
* UD delays use delay node.
|
||||
*
|
||||
|
||||
+62
-1
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: vpi_const.cc,v 1.35 2006/03/18 22:51:10 steve Exp $"
|
||||
#ident "$Id: vpi_const.cc,v 1.36 2006/06/18 04:15:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vpi_priv.h"
|
||||
@@ -529,8 +529,69 @@ vpiHandle vpip_make_dec_const(int value)
|
||||
}
|
||||
|
||||
|
||||
static int real_get(int code, vpiHandle ref)
|
||||
{
|
||||
|
||||
switch (code) {
|
||||
case vpiConstType:
|
||||
return vpiRealConst;
|
||||
|
||||
case vpiSigned:
|
||||
return 1;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "vvp error: get %d not supported "
|
||||
"by vpiDecConst\n", code);
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void real_value(vpiHandle ref, p_vpi_value vp)
|
||||
{
|
||||
struct __vpiRealConst*rfp = (struct __vpiRealConst*)ref;
|
||||
assert(ref->vpi_type->type_code == vpiConstant);
|
||||
|
||||
switch (vp->format) {
|
||||
case vpiObjTypeVal:
|
||||
vp->format = vpiRealVal;
|
||||
case vpiRealVal:
|
||||
vp->value.real = rfp->value;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
static const struct __vpirt vpip_real_rt = {
|
||||
vpiConstant,
|
||||
real_get,
|
||||
0,
|
||||
real_value,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
};
|
||||
|
||||
vpiHandle vpip_make_real_const(struct __vpiRealConst*obj, double value)
|
||||
{
|
||||
obj->base.vpi_type = &vpip_real_rt;
|
||||
obj->value = value;
|
||||
return &(obj->base);
|
||||
}
|
||||
|
||||
vpiHandle vpip_make_real_const(double value)
|
||||
{
|
||||
struct __vpiRealConst*obj;
|
||||
obj =(struct __vpiRealConst*) malloc(sizeof (struct __vpiRealConst));
|
||||
return vpip_make_real_const(obj, value);
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: vpi_const.cc,v $
|
||||
* Revision 1.36 2006/06/18 04:15:50 steve
|
||||
* Add support for system functions in continuous assignments.
|
||||
*
|
||||
* Revision 1.35 2006/03/18 22:51:10 steve
|
||||
* Syntax for carrying sign with parameter.
|
||||
*
|
||||
|
||||
+12
-1
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: vpi_mcd.cc,v 1.12 2004/10/04 01:10:59 steve Exp $"
|
||||
#ident "$Id: vpi_mcd.cc,v 1.13 2006/08/03 05:05:31 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vpi_priv.h"
|
||||
@@ -200,6 +200,14 @@ extern "C" PLI_INT32 vpi_mcd_flush(PLI_UINT32 mcd)
|
||||
/*
|
||||
* MCD/FD Extensions
|
||||
*/
|
||||
|
||||
/*
|
||||
* The vpi_fopen function opens a file with the given path, and
|
||||
* returns a file descriptor that includes bit 31 set. This is to
|
||||
* differentiate the fd from a mcd discriptor. Note that these
|
||||
* descriptors are distinct from the mcd descriptors, so uses a
|
||||
* different fd table.
|
||||
*/
|
||||
extern "C" PLI_INT32 vpi_fopen(const char*name, const char*mode)
|
||||
{
|
||||
unsigned i;
|
||||
@@ -230,6 +238,9 @@ extern "C" FILE *vpi_get_file(PLI_INT32 fd)
|
||||
|
||||
/*
|
||||
* $Log: vpi_mcd.cc,v $
|
||||
* Revision 1.13 2006/08/03 05:05:31 steve
|
||||
* Better comments for vpi_fopen function.
|
||||
*
|
||||
* Revision 1.12 2004/10/04 01:10:59 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
||||
+16
-1
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: vpi_priv.h,v 1.70 2006/03/18 22:51:10 steve Exp $"
|
||||
#ident "$Id: vpi_priv.h,v 1.71 2006/06/18 04:15:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vpi_user.h"
|
||||
@@ -257,6 +257,9 @@ struct __vpiUserSystf {
|
||||
s_vpi_systf_data info;
|
||||
};
|
||||
|
||||
extern struct __vpiUserSystf* vpip_find_systf(const char*name);
|
||||
|
||||
|
||||
struct __vpiSysTaskCall {
|
||||
struct __vpiHandle base;
|
||||
struct __vpiScope* scope;
|
||||
@@ -268,6 +271,7 @@ struct __vpiSysTaskCall {
|
||||
/* These represent where in the vthread to put the return value. */
|
||||
unsigned vbit;
|
||||
signed vwid;
|
||||
class vvp_net_t*fnet;
|
||||
};
|
||||
|
||||
extern struct __vpiSysTaskCall*vpip_cur_task;
|
||||
@@ -309,6 +313,13 @@ struct __vpiDecConst {
|
||||
vpiHandle vpip_make_dec_const(int value);
|
||||
vpiHandle vpip_make_dec_const(struct __vpiDecConst*obj, int value);
|
||||
|
||||
struct __vpiRealConst {
|
||||
struct __vpiHandle base;
|
||||
double value;
|
||||
};
|
||||
|
||||
vpiHandle vpip_make_real_const(double value);
|
||||
|
||||
/*
|
||||
* This one looks like a constant, but really is a vector in the current
|
||||
* thread.
|
||||
@@ -350,6 +361,7 @@ extern unsigned vpip_module_path_cnt;
|
||||
*/
|
||||
extern vpiHandle vpip_build_vpi_call(const char*name,
|
||||
unsigned vbit, int vwid,
|
||||
class vvp_net_t*fnet,
|
||||
unsigned argc,
|
||||
vpiHandle*argv);
|
||||
|
||||
@@ -432,6 +444,9 @@ extern char *need_result_buf(unsigned cnt, vpi_rbuf_t type);
|
||||
|
||||
/*
|
||||
* $Log: vpi_priv.h,v $
|
||||
* Revision 1.71 2006/06/18 04:15:50 steve
|
||||
* Add support for system functions in continuous assignments.
|
||||
*
|
||||
* Revision 1.70 2006/03/18 22:51:10 steve
|
||||
* Syntax for carrying sign with parameter.
|
||||
*
|
||||
|
||||
+124
-11
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: vpi_tasks.cc,v 1.31 2005/09/20 18:34:02 steve Exp $"
|
||||
#ident "$Id: vpi_tasks.cc,v 1.32 2006/06/18 04:15:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -266,6 +266,92 @@ static vpiHandle sysfunc_put_real_value(vpiHandle ref, p_vpi_value vp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static vpiHandle sysfunc_put_4net_value(vpiHandle ref, p_vpi_value vp)
|
||||
{
|
||||
assert(ref->vpi_type->type_code == vpiSysFuncCall);
|
||||
|
||||
struct __vpiSysTaskCall*rfp = (struct __vpiSysTaskCall*)ref;
|
||||
|
||||
unsigned vwid = (unsigned) rfp->vwid;
|
||||
vvp_vector4_t val (vwid);
|
||||
|
||||
switch (vp->format) {
|
||||
|
||||
case vpiIntVal: {
|
||||
long tmp = vp->value.integer;
|
||||
for (unsigned idx = 0 ; idx < vwid ; idx += 1) {
|
||||
val.set_bit(idx, (tmp&1)? BIT4_1 : BIT4_0);
|
||||
tmp >>= 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case vpiVectorVal:
|
||||
|
||||
for (unsigned wdx = 0 ; wdx < vwid ; wdx += 32) {
|
||||
unsigned word = wdx / 32;
|
||||
unsigned long aval = vp->value.vector[word].aval;
|
||||
unsigned long bval = vp->value.vector[word].bval;
|
||||
|
||||
for (unsigned idx = 0 ; (wdx+idx) < vwid ; idx += 1) {
|
||||
int bit = (aval&1) | ((bval<<1)&2);
|
||||
vvp_bit4_t bit4;
|
||||
|
||||
switch (bit) {
|
||||
case 0:
|
||||
bit4 = BIT4_0;
|
||||
break;
|
||||
case 1:
|
||||
bit4 = BIT4_1;
|
||||
break;
|
||||
case 2:
|
||||
bit4 = BIT4_Z;
|
||||
break;
|
||||
case 3:
|
||||
bit4 = BIT4_X;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
val.set_bit(wdx+idx, bit4);
|
||||
|
||||
aval >>= 1;
|
||||
bval >>= 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "XXXX format=%d, vwid=%u\n", vp->format, rfp->vwid);
|
||||
assert(0);
|
||||
}
|
||||
|
||||
vvp_send_vec4(rfp->fnet->out, val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static vpiHandle sysfunc_put_rnet_value(vpiHandle ref, p_vpi_value vp)
|
||||
{
|
||||
assert(ref->vpi_type->type_code == vpiSysFuncCall);
|
||||
|
||||
struct __vpiSysTaskCall*rfp = (struct __vpiSysTaskCall*)ref;
|
||||
double val;
|
||||
|
||||
switch (vp->format) {
|
||||
|
||||
case vpiRealVal:
|
||||
val = vp->value.real;
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
vvp_send_real(rfp->fnet->out, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static const struct __vpirt vpip_sysfunc_rt = {
|
||||
vpiSysFuncCall,
|
||||
@@ -287,6 +373,26 @@ static const struct __vpirt vpip_sysfunc_real_rt = {
|
||||
systask_iter
|
||||
};
|
||||
|
||||
static const struct __vpirt vpip_sysfunc_4net_rt = {
|
||||
vpiSysFuncCall,
|
||||
0,
|
||||
systask_get_str,
|
||||
0,
|
||||
sysfunc_put_4net_value,
|
||||
systask_handle,
|
||||
systask_iter
|
||||
};
|
||||
|
||||
static const struct __vpirt vpip_sysfunc_rnet_rt = {
|
||||
vpiSysFuncCall,
|
||||
0,
|
||||
systask_get_str,
|
||||
0,
|
||||
sysfunc_put_rnet_value,
|
||||
systask_handle,
|
||||
systask_iter
|
||||
};
|
||||
|
||||
/* **** Manipulate the internal datastructures. **** */
|
||||
|
||||
static struct __vpiUserSystf**def_table = 0;
|
||||
@@ -315,7 +421,7 @@ static struct __vpiUserSystf* allocate_def(void)
|
||||
}
|
||||
|
||||
|
||||
static struct __vpiUserSystf* vpip_find_systf(const char*name)
|
||||
struct __vpiUserSystf* vpip_find_systf(const char*name)
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < def_count ; idx += 1)
|
||||
if (strcmp(def_table[idx]->info.tfname, name) == 0)
|
||||
@@ -337,6 +443,7 @@ static struct __vpiUserSystf* vpip_find_systf(const char*name)
|
||||
* vbit is also a non-zero value, the address in thread space of the result.
|
||||
*/
|
||||
vpiHandle vpip_build_vpi_call(const char*name, unsigned vbit, int vwid,
|
||||
class vvp_net_t*fnet,
|
||||
unsigned argc, vpiHandle*argv)
|
||||
{
|
||||
struct __vpiUserSystf*defn = vpip_find_systf(name);
|
||||
@@ -348,7 +455,7 @@ vpiHandle vpip_build_vpi_call(const char*name, unsigned vbit, int vwid,
|
||||
|
||||
switch (defn->info.type) {
|
||||
case vpiSysTask:
|
||||
if (vwid != 0) {
|
||||
if (vwid != 0 || fnet != 0) {
|
||||
fprintf(stderr, "%s: This is a system Task, "
|
||||
"you cannot call it as a Function\n", name);
|
||||
return 0;
|
||||
@@ -357,7 +464,7 @@ vpiHandle vpip_build_vpi_call(const char*name, unsigned vbit, int vwid,
|
||||
break;
|
||||
|
||||
case vpiSysFunc:
|
||||
if (vwid == 0) {
|
||||
if (vwid == 0 && fnet == 0) {
|
||||
fprintf(stderr, "%s: This is a system Function, "
|
||||
"you cannot call it as a Task\n", name);
|
||||
return 0;
|
||||
@@ -376,18 +483,20 @@ vpiHandle vpip_build_vpi_call(const char*name, unsigned vbit, int vwid,
|
||||
break;
|
||||
|
||||
case vpiSysFunc:
|
||||
if (vwid > 0) {
|
||||
obj->base.vpi_type = &vpip_sysfunc_rt;
|
||||
if (fnet && vwid == -vpiRealConst) {
|
||||
obj->base.vpi_type = &vpip_sysfunc_rnet_rt;
|
||||
|
||||
} else switch (vwid) {
|
||||
} else if (fnet && vwid > 0) {
|
||||
obj->base.vpi_type = &vpip_sysfunc_4net_rt;
|
||||
|
||||
case -vpiRealConst:
|
||||
} else if (vwid == -vpiRealConst) {
|
||||
obj->base.vpi_type = &vpip_sysfunc_real_rt;
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
} else if (vwid > 0) {
|
||||
obj->base.vpi_type = &vpip_sysfunc_rt;
|
||||
|
||||
} else {
|
||||
assert(0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -398,6 +507,7 @@ vpiHandle vpip_build_vpi_call(const char*name, unsigned vbit, int vwid,
|
||||
obj->args = argv;
|
||||
obj->vbit = vbit;
|
||||
obj->vwid = vwid;
|
||||
obj->fnet = fnet;
|
||||
obj->userdata = 0;
|
||||
|
||||
/* If there is a compiletf function, call it here. */
|
||||
@@ -487,6 +597,9 @@ void* vpi_get_userdata(vpiHandle ref)
|
||||
|
||||
/*
|
||||
* $Log: vpi_tasks.cc,v $
|
||||
* Revision 1.32 2006/06/18 04:15:50 steve
|
||||
* Add support for system functions in continuous assignments.
|
||||
*
|
||||
* Revision 1.31 2005/09/20 18:34:02 steve
|
||||
* Clean up compiler warnings.
|
||||
*
|
||||
|
||||
+5
-2
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: vpip_bin.cc,v 1.3 2006/02/21 05:31:54 steve Exp $"
|
||||
#ident "$Id: vpip_bin.cc,v 1.4 2006/08/03 05:05:06 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -78,11 +78,14 @@ void vpip_bin_str_to_vec4(vvp_vector4_t&vec4,
|
||||
}
|
||||
|
||||
while (idx < vec4.size())
|
||||
vec4.set_bit(idx, last);
|
||||
vec4.set_bit(idx++, last);
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: vpip_bin.cc,v $
|
||||
* Revision 1.4 2006/08/03 05:05:06 steve
|
||||
* Fix infinite loop padding binary string to result.
|
||||
*
|
||||
* Revision 1.3 2006/02/21 05:31:54 steve
|
||||
* Put strings for reg objects.
|
||||
*
|
||||
|
||||
+84
-7
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: vthread.cc,v 1.152 2006/02/02 05:48:45 steve Exp $"
|
||||
#ident "$Id: vthread.cc,v 1.156 2006/08/09 05:19:08 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -336,6 +336,41 @@ void vthread_run(vthread_t thr)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Unlink a ptr object from the driver. The input is the driver in the
|
||||
* form of a vvp_net_t pointer. The .out member of that object is the
|
||||
* driver. The dst_ptr argument is the receiver pin to be located and
|
||||
* removed from the fan-out list.
|
||||
*/
|
||||
static void unlink_from_driver(vvp_net_t*src, vvp_net_ptr_t dst_ptr)
|
||||
{
|
||||
vvp_net_t*net = dst_ptr.ptr();
|
||||
unsigned net_port = dst_ptr.port();
|
||||
|
||||
if (src->out == dst_ptr) {
|
||||
/* If the drive fan-out list starts with this pointer,
|
||||
then the unlink is easy. Pull the list forward. */
|
||||
src->out = net->port[net_port];
|
||||
} else {
|
||||
/* Scan the linked list, looking for the net_ptr_t
|
||||
pointer *before* the one we wish to remove. */
|
||||
vvp_net_ptr_t cur = src->out;
|
||||
assert(!cur.nil());
|
||||
vvp_net_t*cur_net = cur.ptr();
|
||||
unsigned cur_port = cur.port();
|
||||
while (cur_net->port[cur_port] != dst_ptr) {
|
||||
cur = cur_net->port[cur_port];
|
||||
assert(!cur.nil());
|
||||
cur_net = cur.ptr();
|
||||
cur_port = cur.port();
|
||||
}
|
||||
/* Unlink. */
|
||||
cur_net->port[cur_port] = net->port[net_port];
|
||||
}
|
||||
|
||||
net->port[net_port] = vvp_net_ptr_t(0,0);
|
||||
}
|
||||
|
||||
/*
|
||||
* The CHUNK_LINK instruction is a specla next pointer for linking
|
||||
* chunks of code space. It's like a simplified %jmp.
|
||||
@@ -579,16 +614,17 @@ bool of_ASSIGN_V0X1(vthread_t thr, vvp_code_t cp)
|
||||
bool of_ASSIGN_WR(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
unsigned delay = cp->bit_idx[0];
|
||||
unsigned index = cp->bit_idx[1];
|
||||
s_vpi_time del;
|
||||
|
||||
del.type = vpiSimTime;
|
||||
vpip_time_to_timestruct(&del, schedule_simtime() + delay);
|
||||
vpip_time_to_timestruct(&del, delay);
|
||||
|
||||
struct __vpiHandle*tmp = cp->handle;
|
||||
|
||||
t_vpi_value val;
|
||||
val.format = vpiRealVal;
|
||||
val.value.real = thr->words[cp->bit_idx[1]].w_real;
|
||||
val.value.real = thr->words[index].w_real;
|
||||
vpi_put_value(tmp, &val, &del, vpiInertialDelay);
|
||||
|
||||
return true;
|
||||
@@ -1013,10 +1049,21 @@ bool of_DEASSIGN(vthread_t thr, vvp_code_t cp)
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* The delay takes two 32bit numbers to make up a 64bit time.
|
||||
*
|
||||
* %delay <low>, <hig>
|
||||
*/
|
||||
bool of_DELAY(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
//printf("thread %p: %%delay %lu\n", thr, cp->number);
|
||||
schedule_vthread(thr, cp->number);
|
||||
vvp_time64_t low = cp->bit_idx[0];
|
||||
vvp_time64_t hig = cp->bit_idx[1];
|
||||
|
||||
vvp_time64_t res = 32;
|
||||
res = hig << res;
|
||||
res += low;
|
||||
|
||||
schedule_vthread(thr, res);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -2232,6 +2279,18 @@ bool of_MOD_S(vthread_t thr, vvp_code_t cp)
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* %mod/wr <dest>, <src>
|
||||
*/
|
||||
bool of_MOD_WR(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
double l = thr->words[cp->bit_idx[0]].w_real;
|
||||
double r = thr->words[cp->bit_idx[1]].w_real;
|
||||
thr->words[cp->bit_idx[0]].w_real = fmod(l,r);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* %mov <dest>, <src>, <wid>
|
||||
* This instruction is implemented by the of_MOV function
|
||||
@@ -2753,6 +2812,7 @@ bool of_RELEASE_NET(vthread_t thr, vvp_code_t cp)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool of_RELEASE_REG(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
vvp_net_t*net = cp->net;
|
||||
@@ -2760,9 +2820,14 @@ bool of_RELEASE_REG(vthread_t thr, vvp_code_t cp)
|
||||
vvp_fun_signal_base*sig = reinterpret_cast<vvp_fun_signal_base*>(net->fun);
|
||||
assert(sig);
|
||||
|
||||
/* XXXX Release for %force/link not yet implemented. */
|
||||
assert(sig->force_link == 0);
|
||||
// This is the net that is forcing me...
|
||||
if (vvp_net_t*src = sig->force_link) {
|
||||
// And this is the pointer to be removed.
|
||||
vvp_net_ptr_t dst_ptr (net, 2);
|
||||
unlink_from_driver(src, dst_ptr);
|
||||
}
|
||||
|
||||
// Send a command to this signal to unforce itself.
|
||||
vvp_net_ptr_t ptr (net, 3);
|
||||
vvp_send_long(ptr, 3);
|
||||
|
||||
@@ -3219,6 +3284,18 @@ bool of_JOIN_UFUNC(vthread_t thr, vvp_code_t cp)
|
||||
|
||||
/*
|
||||
* $Log: vthread.cc,v $
|
||||
* Revision 1.156 2006/08/09 05:19:08 steve
|
||||
* Add support for real valued modulus.
|
||||
*
|
||||
* Revision 1.155 2006/08/08 05:11:37 steve
|
||||
* Handle 64bit delay constants.
|
||||
*
|
||||
* Revision 1.154 2006/08/04 04:37:37 steve
|
||||
* Support release of a for/linked reg.
|
||||
*
|
||||
* Revision 1.153 2006/04/27 04:38:00 steve
|
||||
* schedule takes relative, not absolute, time.
|
||||
*
|
||||
* Revision 1.152 2006/02/02 05:48:45 steve
|
||||
* real-to-integer conversions round, not truncate.
|
||||
*
|
||||
|
||||
+42
-6
@@ -16,7 +16,7 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ident "$Id: vvp_net.cc,v 1.52 2006/03/15 19:15:34 steve Exp $"
|
||||
#ident "$Id: vvp_net.cc,v 1.54 2006/07/08 21:48:00 steve Exp $"
|
||||
|
||||
# include "config.h"
|
||||
# include "vvp_net.h"
|
||||
@@ -1296,10 +1296,10 @@ void vvp_net_fun_t::recv_vec8(vvp_net_ptr_t port, vvp_vector8_t bit)
|
||||
recv_vec4(port, reduce4(bit));
|
||||
}
|
||||
|
||||
void vvp_net_fun_t::recv_real(vvp_net_ptr_t, double)
|
||||
void vvp_net_fun_t::recv_real(vvp_net_ptr_t, double bit)
|
||||
{
|
||||
fprintf(stderr, "internal error: %s: recv_real not implemented\n",
|
||||
typeid(*this).name());
|
||||
fprintf(stderr, "internal error: %s: recv_real(%f) not implemented\n",
|
||||
typeid(*this).name(), bit);
|
||||
assert(0);
|
||||
}
|
||||
|
||||
@@ -1709,12 +1709,14 @@ vvp_wide_fun_core::vvp_wide_fun_core(vvp_net_t*net, unsigned nports)
|
||||
{
|
||||
ptr_ = net;
|
||||
nports_ = nports;
|
||||
port_values_ = new vvp_vector4_t [nports_];
|
||||
port_values_ = 0;
|
||||
port_rvalues_ = 0;
|
||||
}
|
||||
|
||||
vvp_wide_fun_core::~vvp_wide_fun_core()
|
||||
{
|
||||
delete[]port_values_;
|
||||
if (port_values_) delete[]port_values_;
|
||||
if (port_rvalues_) delete[]port_rvalues_;
|
||||
}
|
||||
|
||||
void vvp_wide_fun_core::propagate_vec4(const vvp_vector4_t&bit,
|
||||
@@ -1735,17 +1737,39 @@ unsigned vvp_wide_fun_core::port_count() const
|
||||
vvp_vector4_t& vvp_wide_fun_core::value(unsigned idx)
|
||||
{
|
||||
assert(idx < nports_);
|
||||
assert(port_values_);
|
||||
return port_values_[idx];
|
||||
}
|
||||
|
||||
double vvp_wide_fun_core::value_r(unsigned idx)
|
||||
{
|
||||
assert(idx < nports_);
|
||||
return port_rvalues_? port_rvalues_[idx] : 0.0;
|
||||
}
|
||||
|
||||
void vvp_wide_fun_core::recv_real_from_inputs(unsigned p)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
|
||||
void vvp_wide_fun_core::dispatch_vec4_from_input_(unsigned port,
|
||||
vvp_vector4_t bit)
|
||||
{
|
||||
assert(port < nports_);
|
||||
if (port_values_ == 0) port_values_ = new vvp_vector4_t [nports_];
|
||||
port_values_[port] = bit;
|
||||
recv_vec4_from_inputs(port);
|
||||
}
|
||||
|
||||
void vvp_wide_fun_core::dispatch_real_from_input_(unsigned port,
|
||||
double bit)
|
||||
{
|
||||
assert(port < nports_);
|
||||
if (port_rvalues_ == 0) port_rvalues_ = new double[nports_];
|
||||
port_rvalues_[port] = bit;
|
||||
recv_real_from_inputs(port);
|
||||
}
|
||||
|
||||
vvp_wide_fun_t::vvp_wide_fun_t(vvp_wide_fun_core*c, unsigned base)
|
||||
: core_(c), port_base_(base)
|
||||
{
|
||||
@@ -1761,6 +1785,12 @@ void vvp_wide_fun_t::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
|
||||
core_->dispatch_vec4_from_input_(pidx, bit);
|
||||
}
|
||||
|
||||
void vvp_wide_fun_t::recv_real(vvp_net_ptr_t port, double bit)
|
||||
{
|
||||
unsigned pidx = port_base_ + port.port();
|
||||
core_->dispatch_real_from_input_(pidx, bit);
|
||||
}
|
||||
|
||||
|
||||
/* **** vvp_scalar_t methods **** */
|
||||
|
||||
@@ -2163,6 +2193,12 @@ vvp_bit4_t compare_gtge_signed(const vvp_vector4_t&a,
|
||||
|
||||
/*
|
||||
* $Log: vvp_net.cc,v $
|
||||
* Revision 1.54 2006/07/08 21:48:00 steve
|
||||
* Delay object supports real valued delays.
|
||||
*
|
||||
* Revision 1.53 2006/06/18 04:15:50 steve
|
||||
* Add support for system functions in continuous assignments.
|
||||
*
|
||||
* Revision 1.52 2006/03/15 19:15:34 steve
|
||||
* const/non-const clash.
|
||||
*
|
||||
|
||||
+26
-2
@@ -18,7 +18,7 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ident "$Id: vvp_net.h,v 1.50 2006/03/08 05:29:42 steve Exp $"
|
||||
#ident "$Id: vvp_net.h,v 1.52 2006/08/04 04:37:37 steve Exp $"
|
||||
|
||||
# include "config.h"
|
||||
# include <stddef.h>
|
||||
@@ -478,6 +478,9 @@ class vvp_net_ptr_t {
|
||||
|
||||
bool nil() const;
|
||||
|
||||
bool operator == (vvp_net_ptr_t that) const;
|
||||
bool operator != (vvp_net_ptr_t that) const;
|
||||
|
||||
private:
|
||||
unsigned long bits_;
|
||||
};
|
||||
@@ -522,6 +525,16 @@ inline bool vvp_net_ptr_t::nil() const
|
||||
return bits_ == 0;
|
||||
}
|
||||
|
||||
inline bool vvp_net_ptr_t::operator == (vvp_net_ptr_t that) const
|
||||
{
|
||||
return bits_ == that.bits_;
|
||||
}
|
||||
|
||||
inline bool vvp_net_ptr_t::operator != (vvp_net_ptr_t that) const
|
||||
{
|
||||
return bits_ != that.bits_;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This is the basic unit of netlist connectivity. It is a fan-in of
|
||||
@@ -918,15 +931,19 @@ class vvp_wide_fun_core : public vvp_net_fun_t {
|
||||
protected:
|
||||
void propagate_vec4(const vvp_vector4_t&bit, vvp_time64_t delay =0);
|
||||
unsigned port_count() const;
|
||||
|
||||
vvp_vector4_t& value(unsigned);
|
||||
double value_r(unsigned);
|
||||
|
||||
private:
|
||||
// the derived class implements this to receive an indication
|
||||
// that one of the port input values changed.
|
||||
virtual void recv_vec4_from_inputs(unsigned port) =0;
|
||||
virtual void recv_real_from_inputs(unsigned port);
|
||||
|
||||
friend class vvp_wide_fun_t;
|
||||
void dispatch_vec4_from_input_(unsigned port, vvp_vector4_t bit);
|
||||
void dispatch_real_from_input_(unsigned port, double bit);
|
||||
|
||||
private:
|
||||
// Back-point to the vvp_net_t that points to me.
|
||||
@@ -934,7 +951,7 @@ class vvp_wide_fun_core : public vvp_net_fun_t {
|
||||
// Structure to track the input values from the input functors.
|
||||
unsigned nports_;
|
||||
vvp_vector4_t*port_values_;
|
||||
|
||||
double*port_rvalues_;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -950,6 +967,7 @@ class vvp_wide_fun_t : public vvp_net_fun_t {
|
||||
~vvp_wide_fun_t();
|
||||
|
||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit);
|
||||
void recv_real(vvp_net_ptr_t port, double bit);
|
||||
|
||||
private:
|
||||
vvp_wide_fun_core*core_;
|
||||
@@ -1008,6 +1026,12 @@ inline void vvp_send_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&val,
|
||||
|
||||
/*
|
||||
* $Log: vvp_net.h,v $
|
||||
* Revision 1.52 2006/08/04 04:37:37 steve
|
||||
* Support release of a for/linked reg.
|
||||
*
|
||||
* Revision 1.51 2006/06/18 04:15:50 steve
|
||||
* Add support for system functions in continuous assignments.
|
||||
*
|
||||
* Revision 1.50 2006/03/08 05:29:42 steve
|
||||
* Add support for logic parameters.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user