Compare commits

...
58 Commits
Author SHA1 Message Date
steve 54c7ef72cb Snapshot 20060809 2006-08-10 01:23:29 +00:00
steve 50800fd3a1 Add support for real valued modulus. 2006-08-09 05:19:08 +00:00
steve fc0695beb6 Handle 64bit delay constants. 2006-08-08 05:11:37 +00:00
steve 00891db0d2 Fix typo in initialize of new event_time cell. 2006-08-06 18:17:00 +00:00
steve 898b0e0365 Support release of a for/linked reg. 2006-08-04 04:37:37 +00:00
steve 382c4d74fd Add the scanf functions. 2006-08-03 05:06:04 +00:00
steve 5bcf083662 Better comments for vpi_fopen function. 2006-08-03 05:05:31 +00:00
steve 1bd530c144 Fix infinite loop padding binary string to result. 2006-08-03 05:05:06 +00:00
steve 82a85131a8 Use compiletf to check arguments. 2006-08-03 05:02:46 +00:00
steve 49b65e86fe Add support for power in constant expressions. 2006-07-31 03:50:17 +00:00
steve 06d6ac4b33 Fix/implement signed right shift. 2006-07-30 02:51:35 +00:00
steve 2037650080 Pass depfiles through temp defines file. 2006-07-26 00:11:40 +00:00
steve 61f3a84557 Pass defines and includes through temp file. 2006-07-26 00:02:48 +00:00
steve ed70db84ce Handle real valued literals in net contexts. 2006-07-08 21:48:46 +00:00
steve 5348ac14a5 Delay object supports real valued delays. 2006-07-08 21:48:00 +00:00
steve aab6fefd8a Fix context determined with of constants. 2006-07-07 04:06:37 +00:00
steve 1b8e2a17c7 Change the Copyright tag to License. 2006-06-24 05:21:07 +00:00
steve 33a391cb71 Sign extend operands of signed addition. 2006-06-20 05:06:47 +00:00
steve bcc08112aa Snapshot 20060618 2006-06-18 23:56:23 +00:00
steve 80f30be9d0 Add support for system functions in continuous assignments. 2006-06-18 04:15:50 +00:00
steve 71faebd6df 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.
2006-06-02 04:48:49 +00:00
steve 53ae1f29c9 Fix broken subtraction of small constants. 2006-06-01 03:54:51 +00:00
steve 857b3e15b6 Fix handling of ternary-to-bufif0 constant propagation. 2006-05-24 04:32:57 +00:00
steve 019d61f633 Get self-determined unary - width right. 2006-05-19 04:44:55 +00:00
steve d37b6599f4 eval_const is not strict. 2006-05-19 04:07:24 +00:00
steve 68e52ce6b7 Synchronous primitives only follow edges. 2006-05-18 05:13:45 +00:00
steve 4c885f65e1 Error message if concat expression cannot evaluate. 2006-05-17 16:49:30 +00:00
steve f0e114d59f Lexor os never interactive. 2006-05-17 04:15:12 +00:00
steve aaaa042f73 Add port list format for task arguments. 2006-05-11 03:26:57 +00:00
steve 044da54b41 Be more stubborn about widths. 2006-05-02 04:29:42 +00:00
steve a8b86ea3bb More explicit datatype setup. 2006-05-01 20:47:58 +00:00
steve e98aad1e9b Cleaner rule for parse.h and parse.cc 2006-05-01 20:47:29 +00:00
steve 1ef91f800f Forgot to invert nand output. 2006-05-01 20:47:03 +00:00
steve a19efe181b Install stub target. 2006-05-01 18:48:24 +00:00
steve 81bfbd1549 Reduce steps to make logic output. 2006-05-01 18:44:08 +00:00
steve dc2898cc73 fix net type of multiply output. 2006-05-01 05:40:21 +00:00
steve 0c9fb766b6 Get the data type of part select results right. 2006-04-30 05:17:48 +00:00
steve 10f8c66f4a Dump *all* the reduction operator gates. 2006-04-30 05:16:53 +00:00
steve 56f70ec702 Include math.h with lround implementation. 2006-04-28 15:44:37 +00:00
steve 949054e000 lround takes double, not float. 2006-04-28 15:40:30 +00:00
steve 47b72c3b74 Handle padding of MUX net results. 2006-04-28 05:09:51 +00:00
steve a2c036d5ab Allow concatenations as arguments to inout ports. 2006-04-28 04:28:35 +00:00
steve 0d17e57656 Dump indexes of ident expressions 2006-04-28 04:19:31 +00:00
steve fd94268315 Detect missing lround function. 2006-04-27 05:04:59 +00:00
steve 36039e13ec schedule takes relative, not absolute, time. 2006-04-27 04:38:00 +00:00
steve a702f99c04 Dump function type as string. 2006-04-27 04:26:38 +00:00
steve 4493e3f928 Chop down assign r-values that elaborate too wide. 2006-04-26 04:43:50 +00:00
steve 3727052000 Include bit value in assertion message. 2006-04-26 04:39:23 +00:00
steve 39ff233cf1 Detect the presence of stdint.h 2006-04-25 22:41:10 +00:00
steve 58118bddc5 Warning when file is inadequate for requested range. 2006-04-25 05:00:12 +00:00
steve c2ff3d501c Fix support for indexed part select in continuous assign l-values. 2006-04-24 05:15:07 +00:00
steve 46d86ad276 Get tail counts right in nested concatenations. 2006-04-22 04:27:36 +00:00
steve 4dd1308eb0 Parse specify ifnone statements. 2006-04-17 04:35:49 +00:00
steve a978bb1e14 Cleanup lval part select handling. 2006-04-16 00:54:04 +00:00
steve 707af782b3 Fix part selects in l-values. 2006-04-16 00:15:43 +00:00
steve fc5cf55400 Use elab_and_eval to evaluate genvar expressions. 2006-04-12 05:05:03 +00:00
steve 6a74a090f0 Configure for stub. 2006-04-10 03:07:07 +00:00
steve c448b75f2c fpga target is not installed. 2006-04-10 03:05:54 +00:00
89 changed files with 3472 additions and 764 deletions
+2 -4
View File
@@ -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
View File
@@ -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.
*
+50 -14
View File
@@ -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
View File
@@ -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=.. )
+48 -53
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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.
*
+8 -1
View File
@@ -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.
*
+16 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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.
*
+4 -1
View File
@@ -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; }
+1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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.
*
+60 -5
View File
@@ -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
View File
@@ -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.
*
+8 -2
View File
@@ -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.
*
+184 -24
View File
@@ -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
+6 -3
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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.
*
+61 -18
View File
@@ -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.
*
+17 -11
View File
@@ -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.
*
+11 -1
View File
@@ -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.
*
+5 -1
View File
@@ -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.
*
+4
View File
@@ -1,3 +1,7 @@
*.cache
stub.tgt
configure
config.log
config.status
Makefile
dep
+9 -2
View File
@@ -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)
+26
View File
@@ -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)
+2 -2
View File
@@ -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;
+1
View File
@@ -4,3 +4,4 @@ functor:syn-rules
functor:cprop
functor:nodangle
-t:dll
flag:DLL=stub.tgt
+91 -12
View File
@@ -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
View File
@@ -1,3 +1,4 @@
functor:cprop
functor:nodangle
-t:dll
flag:DLL=stub.tgt
+9 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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.
*
+27 -3
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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.
*
+5 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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.
*