Compare commits
152 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
4d4a693248 | |
|
|
1872652019 | |
|
|
d68fea3f58 | |
|
|
b0e2185ade | |
|
|
6aaf2f84a8 | |
|
|
7ad50f4454 | |
|
|
19b0d5b7c9 | |
|
|
ae87aff745 | |
|
|
9c09394785 | |
|
|
3f8f81568a | |
|
|
bb5d30ead5 | |
|
|
4e77abca44 | |
|
|
902ae19bbf | |
|
|
5587e42e2e | |
|
|
f8f363a0b6 | |
|
|
f34485d415 | |
|
|
df177e9e14 | |
|
|
5d4c8d616a | |
|
|
72c02a8285 | |
|
|
043c86ba02 | |
|
|
b9d0783ad9 | |
|
|
047ee137ed | |
|
|
ef814a9ef4 | |
|
|
fa0ecb3761 | |
|
|
f2a81cf660 | |
|
|
e1b4d531a1 | |
|
|
a418995988 | |
|
|
8c36e20fd4 | |
|
|
2c982a6edb | |
|
|
a298bfb22a | |
|
|
cce61d7134 | |
|
|
aad5443a36 | |
|
|
f5f104f8a6 | |
|
|
b7ff68c3f4 | |
|
|
69986a5bc7 | |
|
|
c0f4b0374a | |
|
|
817b1ef3d4 | |
|
|
f9774758a3 | |
|
|
eb2fed7015 | |
|
|
5af47cda12 | |
|
|
0aad444bbf | |
|
|
e63c75d1a3 | |
|
|
a5b0872016 | |
|
|
f6b9db1c78 | |
|
|
597097eaef | |
|
|
47512e351f | |
|
|
506c09f5f8 | |
|
|
693fb93962 | |
|
|
8ca5926db9 | |
|
|
7acafd128f | |
|
|
d0a12f5b14 | |
|
|
8964a175f8 | |
|
|
97d70f9069 | |
|
|
0dc0fbf78d | |
|
|
786b3a0ca9 | |
|
|
24a60ce6af | |
|
|
4c640f67cb | |
|
|
cfe68fe6b4 | |
|
|
78149e9d15 | |
|
|
bbe037bf9f | |
|
|
d3bf6be7b2 | |
|
|
6146a98278 | |
|
|
63c7285113 | |
|
|
79e0203280 | |
|
|
ad419dfbe4 | |
|
|
75d71fe312 | |
|
|
5a30355faf | |
|
|
623e897e55 | |
|
|
0bb6360ac7 | |
|
|
4b850e1e74 | |
|
|
8ce807a263 | |
|
|
cc9524bd89 | |
|
|
13e07d6b7c | |
|
|
bbf11b830b | |
|
|
d345fb7654 | |
|
|
3186e3dc54 | |
|
|
d4d50fd97d | |
|
|
3337c9d51a | |
|
|
dfda202f14 | |
|
|
5ca440dc1c | |
|
|
96908e2fc5 | |
|
|
9f07e3c16e | |
|
|
3ae3e34732 | |
|
|
372efd8c30 | |
|
|
ac7f55f22a | |
|
|
b74736c784 | |
|
|
7988ef04d8 | |
|
|
61214108fe | |
|
|
356a19c918 | |
|
|
f1c5b58845 | |
|
|
fad37da1dc | |
|
|
80f74d0d24 | |
|
|
d25f689f55 | |
|
|
42618741d9 | |
|
|
9bcfc8ab6d | |
|
|
de75e71152 | |
|
|
5f8f7bc6fc | |
|
|
f7fb754ee8 | |
|
|
e59a6b8df7 | |
|
|
f149a30045 | |
|
|
ddaba5b017 | |
|
|
dff535923f | |
|
|
d66471c449 | |
|
|
b16e3ab59e | |
|
|
d7b76e9390 | |
|
|
6f692e7984 | |
|
|
dfe7279488 | |
|
|
b9ea0036de | |
|
|
fc24624fa2 | |
|
|
cca3d5907c | |
|
|
ec809c9137 | |
|
|
682e54841c | |
|
|
7d2734c9cc | |
|
|
74df582c73 | |
|
|
10b8055a38 | |
|
|
95848eb2f8 | |
|
|
efc3bbd29e | |
|
|
c56f21a20c | |
|
|
17210d5423 | |
|
|
b1af2f8535 | |
|
|
aa28430832 | |
|
|
ceea5d568c | |
|
|
710ad582ed | |
|
|
183137b60c | |
|
|
9c7c719cac | |
|
|
2f3061c158 | |
|
|
af08ff64c7 | |
|
|
036c176e8b | |
|
|
327e8d0ec0 | |
|
|
cfb45e56e2 | |
|
|
809044cbf8 | |
|
|
2a53255445 | |
|
|
4205752bb0 | |
|
|
d237e35076 | |
|
|
90f37fe3cb | |
|
|
4be2f61b53 | |
|
|
f8aa9073ac | |
|
|
9ea20d6677 | |
|
|
9fec1f7e45 | |
|
|
c47ea0721c | |
|
|
ef12137931 | |
|
|
0e8a12eebf | |
|
|
9473e823ed | |
|
|
c75f9db315 | |
|
|
1d31a91b4f | |
|
|
b795d8c1d8 | |
|
|
5ec7731e04 | |
|
|
bb29e1d588 | |
|
|
74fd1865cb | |
|
|
b40b6fb50d | |
|
|
19b68f6332 | |
|
|
c96e4da9e4 |
4
Attrib.h
4
Attrib.h
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef __Attrib_H
|
#ifndef __Attrib_H
|
||||||
#define __Attrib_H
|
#define __Attrib_H
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2000-2009 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -30,7 +30,7 @@ class Attrib {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Attrib();
|
Attrib();
|
||||||
~Attrib();
|
virtual ~Attrib();
|
||||||
|
|
||||||
const verinum&attribute(perm_string key) const;
|
const verinum&attribute(perm_string key) const;
|
||||||
void attribute(perm_string key, const verinum&value);
|
void attribute(perm_string key, const verinum&value);
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef __LineInfo_H
|
#ifndef __LineInfo_H
|
||||||
#define __LineInfo_H
|
#define __LineInfo_H
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1999 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 1999-2009 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -36,7 +36,7 @@ using namespace std;
|
||||||
class LineInfo {
|
class LineInfo {
|
||||||
public:
|
public:
|
||||||
LineInfo();
|
LineInfo();
|
||||||
~LineInfo();
|
virtual ~LineInfo();
|
||||||
|
|
||||||
// Get a fully formatted file/lineno
|
// Get a fully formatted file/lineno
|
||||||
string get_fileline() const;
|
string get_fileline() const;
|
||||||
|
|
|
||||||
|
|
@ -223,15 +223,16 @@ endif
|
||||||
version_tag.h version:
|
version_tag.h version:
|
||||||
@if $(GIT_PRESENT) && test -d $(srcdir)/.git; then \
|
@if $(GIT_PRESENT) && test -d $(srcdir)/.git; then \
|
||||||
echo "Using git-describe for VERSION_TAG"; \
|
echo "Using git-describe for VERSION_TAG"; \
|
||||||
tmp=`$(GIT) --git-dir $(srcdir)/.git describe \
|
tag=`$(GIT) --git-dir $(srcdir)/.git describe`; \
|
||||||
| sed -e 's;\(.*\);#define VERSION_TAG "\1";'`; \
|
tmp=`printf "#ifndef VERSION_TAG\n#define VERSION_TAG \"$$tag\"\n#endif\n"`; \
|
||||||
echo "$$tmp" | diff - version_tag.h > /dev/null 2>&1 || echo "$$tmp" > version_tag.h || exit 1; \
|
echo "$$tmp" | diff - version_tag.h > /dev/null 2>&1 || echo "$$tmp" > version_tag.h || exit 1; \
|
||||||
elif test -r $(srcdir)/version_tag.h; then \
|
elif test -r $(srcdir)/version_tag.h; then \
|
||||||
echo "Using $(srcdir)/version_tag.h for VERSION_TAG"; \
|
echo "Using $(srcdir)/version_tag.h for VERSION_TAG"; \
|
||||||
diff $(srcdir)/version_tag.h version_tag.h > /dev/null 2>&1 || cp $(srcdir)/version_tag.h version_tag.h; \
|
diff $(srcdir)/version_tag.h version_tag.h > /dev/null 2>&1 || cp $(srcdir)/version_tag.h version_tag.h; \
|
||||||
else \
|
else \
|
||||||
echo "Using empty VERSION_TAG"; \
|
echo "Using empty VERSION_TAG"; \
|
||||||
echo '#define VERSION_TAG ""' > version_tag.h; \
|
tmp=`printf "#ifndef VERSION_TAG\n#define VERSION_TAG \"\"\n#endif\n"`; \
|
||||||
|
echo "$$tmp" | diff - version_tag.h > /dev/null 2>&1 || echo "$$tmp" > version_tag.h || exit 1; \
|
||||||
fi
|
fi
|
||||||
|
|
||||||
ifeq (@MINGW32@,yes)
|
ifeq (@MINGW32@,yes)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1998-2008 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 1998-2009 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -29,7 +29,10 @@ Module::Module(perm_string n)
|
||||||
: PScope(n)
|
: PScope(n)
|
||||||
{
|
{
|
||||||
library_flag = false;
|
library_flag = false;
|
||||||
|
is_cell = false;
|
||||||
|
uc_drive = UCD_NONE;
|
||||||
default_nettype = NetNet::NONE;
|
default_nettype = NetNet::NONE;
|
||||||
|
timescale_warn_done = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Module::~Module()
|
Module::~Module()
|
||||||
|
|
|
||||||
9
Module.h
9
Module.h
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef __Module_H
|
#ifndef __Module_H
|
||||||
#define __Module_H
|
#define __Module_H
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1998-2008 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 1998-2009 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -74,6 +74,11 @@ class Module : public PScope, public LineInfo {
|
||||||
other effect. */
|
other effect. */
|
||||||
bool library_flag;
|
bool library_flag;
|
||||||
|
|
||||||
|
bool is_cell;
|
||||||
|
|
||||||
|
enum UCDriveType { UCD_NONE, UCD_PULL0, UCD_PULL1 };
|
||||||
|
UCDriveType uc_drive;
|
||||||
|
|
||||||
NetNet::Type default_nettype;
|
NetNet::Type default_nettype;
|
||||||
|
|
||||||
/* specparams are simpler then other params, in that they have
|
/* specparams are simpler then other params, in that they have
|
||||||
|
|
@ -105,6 +110,8 @@ class Module : public PScope, public LineInfo {
|
||||||
/* These are the timescale for this module. The default is
|
/* These are the timescale for this module. The default is
|
||||||
set by the `timescale directive. */
|
set by the `timescale directive. */
|
||||||
int time_unit, time_precision;
|
int time_unit, time_precision;
|
||||||
|
bool time_from_timescale;
|
||||||
|
bool timescale_warn_done;
|
||||||
|
|
||||||
/* Task definitions within this module */
|
/* Task definitions within this module */
|
||||||
map<perm_string,PTask*> tasks;
|
map<perm_string,PTask*> tasks;
|
||||||
|
|
|
||||||
53
PDelays.cc
53
PDelays.cc
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1999-2008 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 1999-2009 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -26,6 +26,11 @@
|
||||||
# include "verinum.h"
|
# include "verinum.h"
|
||||||
# include "netmisc.h"
|
# include "netmisc.h"
|
||||||
|
|
||||||
|
bool dly_used_no_timescale = false;
|
||||||
|
bool dly_used_timescale = false;
|
||||||
|
bool display_ts_dly_warning = true;
|
||||||
|
|
||||||
|
|
||||||
PDelays::PDelays()
|
PDelays::PDelays()
|
||||||
{
|
{
|
||||||
delete_flag_ = true;
|
delete_flag_ = true;
|
||||||
|
|
@ -60,12 +65,28 @@ void PDelays::set_delays(const svector<PExpr*>*del, bool df)
|
||||||
delete_flag_ = df;
|
delete_flag_ = df;
|
||||||
}
|
}
|
||||||
|
|
||||||
static NetExpr*calculate_val(Design*des, NetScope*scope, const PExpr*expr)
|
static NetExpr*calculate_val(Design*des, NetScope*scope, PExpr*expr)
|
||||||
{
|
{
|
||||||
|
ivl_variable_type_t tmp_type = IVL_VT_NO_TYPE;
|
||||||
|
bool tmp_flag = false;
|
||||||
|
expr->test_width(des, scope, 0, 0, tmp_type, tmp_flag);
|
||||||
NetExpr*dex = expr->elaborate_expr(des, scope, -1, false);
|
NetExpr*dex = expr->elaborate_expr(des, scope, -1, false);
|
||||||
eval_expr(dex);
|
eval_expr(dex);
|
||||||
|
|
||||||
|
/* Print a warning if we find default and `timescale based
|
||||||
|
* delays in the design, since this is likely an error. */
|
||||||
|
if (scope->time_from_timescale()) dly_used_timescale = true;
|
||||||
|
else dly_used_no_timescale = true;
|
||||||
|
|
||||||
|
if (display_ts_dly_warning &&
|
||||||
|
dly_used_no_timescale && dly_used_timescale) {
|
||||||
|
cerr << "warning: Found both default and "
|
||||||
|
"`timescale based delays. Use" << endl;
|
||||||
|
cerr << " -Wtimescale to find the "
|
||||||
|
"module(s) with no `timescale." << endl;
|
||||||
|
display_ts_dly_warning = false;
|
||||||
|
}
|
||||||
|
|
||||||
/* If the delay expression is a real constant or vector
|
/* If the delay expression is a real constant or vector
|
||||||
constant, then evaluate it, scale it to the local time
|
constant, then evaluate it, scale it to the local time
|
||||||
units, and return an adjusted value. */
|
units, and return an adjusted value. */
|
||||||
|
|
@ -119,6 +140,20 @@ static NetExpr* make_delay_nets(Design*des, NetScope*scope, NetExpr*expr)
|
||||||
return expr;
|
return expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static NetExpr* calc_decay_time(NetExpr *rise, NetExpr *fall)
|
||||||
|
{
|
||||||
|
NetEConst *c_rise = dynamic_cast<NetEConst*>(rise);
|
||||||
|
NetEConst *c_fall = dynamic_cast<NetEConst*>(fall);
|
||||||
|
if (c_rise && c_fall) {
|
||||||
|
if (c_rise->value() < c_fall->value()) return rise;
|
||||||
|
else return fall;
|
||||||
|
}
|
||||||
|
|
||||||
|
cerr << fall->get_fileline() << ": sorry: can not calculate the "
|
||||||
|
<< "decay time from " << *rise << " and " << *fall << endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void PDelays::eval_delays(Design*des, NetScope*scope,
|
void PDelays::eval_delays(Design*des, NetScope*scope,
|
||||||
NetExpr*&rise_time,
|
NetExpr*&rise_time,
|
||||||
NetExpr*&fall_time,
|
NetExpr*&fall_time,
|
||||||
|
|
@ -140,14 +175,14 @@ void PDelays::eval_delays(Design*des, NetScope*scope,
|
||||||
|
|
||||||
if (delay_[2]) {
|
if (delay_[2]) {
|
||||||
decay_time = calculate_val(des, scope, delay_[2]);
|
decay_time = calculate_val(des, scope, delay_[2]);
|
||||||
if (as_nets_flag)
|
if (as_nets_flag)
|
||||||
decay_time = make_delay_nets(des, scope, decay_time);
|
decay_time = make_delay_nets(des, scope,
|
||||||
|
decay_time);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (rise_time < fall_time)
|
// If this is zero then we need to do the min()
|
||||||
decay_time = rise_time;
|
// at run time.
|
||||||
else
|
decay_time = calc_decay_time(rise_time, fall_time);
|
||||||
decay_time = fall_time;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
assert(delay_[2] == 0);
|
assert(delay_[2] == 0);
|
||||||
|
|
|
||||||
6
PExpr.h
6
PExpr.h
|
|
@ -339,6 +339,12 @@ class PEIdent : public PExpr {
|
||||||
NetScope*found,
|
NetScope*found,
|
||||||
const NetExpr*par_msb,
|
const NetExpr*par_msb,
|
||||||
const NetExpr*par_lsb) const;
|
const NetExpr*par_lsb) const;
|
||||||
|
NetExpr*elaborate_expr_param_idx_do_(Design*des,
|
||||||
|
NetScope*scope,
|
||||||
|
const NetExpr*par,
|
||||||
|
NetScope*found,
|
||||||
|
const NetExpr*par_msb,
|
||||||
|
const NetExpr*par_lsb) const;
|
||||||
NetExpr*elaborate_expr_net(Design*des,
|
NetExpr*elaborate_expr_net(Design*des,
|
||||||
NetScope*scope,
|
NetScope*scope,
|
||||||
NetNet*net,
|
NetNet*net,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2006,2009 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -55,6 +55,7 @@ void PGenerate::probe_for_direct_nesting_(void)
|
||||||
if (localparams.size() > 0) return;
|
if (localparams.size() > 0) return;
|
||||||
if (events.size() > 0) return;
|
if (events.size() > 0) return;
|
||||||
if (wires.size() > 0) return;
|
if (wires.size() > 0) return;
|
||||||
|
if (genvars.size() > 0) return;
|
||||||
if (behaviors.size() > 0) return;
|
if (behaviors.size() > 0) return;
|
||||||
if (analog_behaviors.size() > 0) return;
|
if (analog_behaviors.size() > 0) return;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef __PGenerate_H
|
#ifndef __PGenerate_H
|
||||||
#define __PGenerate_H
|
#define __PGenerate_H
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2008 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2006-2009 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -87,6 +87,9 @@ class PGenerate : public LineInfo, public LexicalScope {
|
||||||
map<perm_string,PTask*> tasks;
|
map<perm_string,PTask*> tasks;
|
||||||
map<perm_string,PFunction*>funcs;
|
map<perm_string,PFunction*>funcs;
|
||||||
|
|
||||||
|
// genvars declared within this scheme.
|
||||||
|
map<perm_string,LineInfo*> genvars;
|
||||||
|
|
||||||
// Generate schemes can contain further generate schemes.
|
// Generate schemes can contain further generate schemes.
|
||||||
list<PGenerate*> generate_schemes;
|
list<PGenerate*> generate_schemes;
|
||||||
PGenerate*parent;
|
PGenerate*parent;
|
||||||
|
|
@ -109,8 +112,8 @@ class PGenerate : public LineInfo, public LexicalScope {
|
||||||
bool generate_scope_case_(Design*des, NetScope*container);
|
bool generate_scope_case_(Design*des, NetScope*container);
|
||||||
bool generate_scope_nblock_(Design*des, NetScope*container);
|
bool generate_scope_nblock_(Design*des, NetScope*container);
|
||||||
|
|
||||||
// Call probe during elaborate_scope to calulate the
|
// Call probe during elaborate_scope to calculate the
|
||||||
// directed_nested_ flag. It is OK to store the direct_nested_
|
// direct_nested_ flag. It is OK to store the direct_nested_
|
||||||
// information here because "direct nested" is a property of
|
// information here because "direct nested" is a property of
|
||||||
// the lexical generate code.
|
// the lexical generate code.
|
||||||
void probe_for_direct_nesting_(void);
|
void probe_for_direct_nesting_(void);
|
||||||
|
|
|
||||||
16
PWire.cc
16
PWire.cc
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1999-2007 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 1999-2009 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -29,8 +29,8 @@ PWire::PWire(perm_string n,
|
||||||
: name_(n), type_(t), port_type_(pt), data_type_(dt),
|
: name_(n), type_(t), port_type_(pt), data_type_(dt),
|
||||||
signed_(false), isint_(false),
|
signed_(false), isint_(false),
|
||||||
port_msb_(0), port_lsb_(0), port_set_(false),
|
port_msb_(0), port_lsb_(0), port_set_(false),
|
||||||
net_msb_(0), net_lsb_(0), net_set_(false), error_cnt_(0),
|
net_msb_(0), net_lsb_(0), net_set_(false), is_scalar_(false),
|
||||||
lidx_(0), ridx_(0), discipline_(0)
|
error_cnt_(0), lidx_(0), ridx_(0), discipline_(0)
|
||||||
{
|
{
|
||||||
if (t == NetNet::INTEGER) {
|
if (t == NetNet::INTEGER) {
|
||||||
type_ = NetNet::REG;
|
type_ = NetNet::REG;
|
||||||
|
|
@ -135,7 +135,12 @@ bool PWire::get_isint() const
|
||||||
return isint_;
|
return isint_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PWire::set_range(PExpr*m, PExpr*l, PWSRType type)
|
bool PWire::get_scalar() const
|
||||||
|
{
|
||||||
|
return is_scalar_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PWire::set_range(PExpr*m, PExpr*l, PWSRType type, bool is_scalar)
|
||||||
{
|
{
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case SR_PORT:
|
case SR_PORT:
|
||||||
|
|
@ -147,6 +152,7 @@ void PWire::set_range(PExpr*m, PExpr*l, PWSRType type)
|
||||||
port_msb_ = m;
|
port_msb_ = m;
|
||||||
port_lsb_ = l;
|
port_lsb_ = l;
|
||||||
port_set_ = true;
|
port_set_ = true;
|
||||||
|
is_scalar_ = is_scalar;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -159,6 +165,7 @@ void PWire::set_range(PExpr*m, PExpr*l, PWSRType type)
|
||||||
net_msb_ = m;
|
net_msb_ = m;
|
||||||
net_lsb_ = l;
|
net_lsb_ = l;
|
||||||
net_set_ = true;
|
net_set_ = true;
|
||||||
|
is_scalar_ = is_scalar;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -181,6 +188,7 @@ void PWire::set_range(PExpr*m, PExpr*l, PWSRType type)
|
||||||
net_msb_ = m;
|
net_msb_ = m;
|
||||||
net_lsb_ = l;
|
net_lsb_ = l;
|
||||||
net_set_ = true;
|
net_set_ = true;
|
||||||
|
is_scalar_ = is_scalar;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
6
PWire.h
6
PWire.h
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef __PWire_H
|
#ifndef __PWire_H
|
||||||
#define __PWire_H
|
#define __PWire_H
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1998-2007 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 1998-2009 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -70,11 +70,12 @@ class PWire : public LineInfo {
|
||||||
void set_signed(bool flag);
|
void set_signed(bool flag);
|
||||||
bool get_signed() const;
|
bool get_signed() const;
|
||||||
bool get_isint() const;
|
bool get_isint() const;
|
||||||
|
bool get_scalar() const;
|
||||||
|
|
||||||
bool set_data_type(ivl_variable_type_t dt);
|
bool set_data_type(ivl_variable_type_t dt);
|
||||||
ivl_variable_type_t get_data_type() const;
|
ivl_variable_type_t get_data_type() const;
|
||||||
|
|
||||||
void set_range(PExpr*msb, PExpr*lsb, PWSRType type);
|
void set_range(PExpr*msb, PExpr*lsb, PWSRType type, bool is_scalar);
|
||||||
|
|
||||||
void set_memory_idx(PExpr*ldx, PExpr*rdx);
|
void set_memory_idx(PExpr*ldx, PExpr*rdx);
|
||||||
|
|
||||||
|
|
@ -104,6 +105,7 @@ class PWire : public LineInfo {
|
||||||
PExpr*net_msb_;
|
PExpr*net_msb_;
|
||||||
PExpr*net_lsb_;
|
PExpr*net_lsb_;
|
||||||
bool net_set_;
|
bool net_set_;
|
||||||
|
bool is_scalar_;
|
||||||
unsigned error_cnt_;
|
unsigned error_cnt_;
|
||||||
|
|
||||||
// If this wire is actually a memory, these indices will give
|
// If this wire is actually a memory, these indices will give
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2004 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2002-2009 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -25,6 +25,11 @@
|
||||||
# include <string.h>
|
# include <string.h>
|
||||||
# include <assert.h>
|
# include <assert.h>
|
||||||
|
|
||||||
|
#ifdef CHECK_WITH_VALGRIND
|
||||||
|
static char **string_pool = NULL;
|
||||||
|
static unsigned string_pool_count = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
StringHeap::StringHeap()
|
StringHeap::StringHeap()
|
||||||
{
|
{
|
||||||
cell_base_ = 0;
|
cell_base_ = 0;
|
||||||
|
|
@ -46,6 +51,12 @@ const char* StringHeap::add(const char*text)
|
||||||
unsigned rem = HEAPCELL - cell_ptr_;
|
unsigned rem = HEAPCELL - cell_ptr_;
|
||||||
if (rem < (len+1)) {
|
if (rem < (len+1)) {
|
||||||
cell_base_ = (char*)malloc(HEAPCELL);
|
cell_base_ = (char*)malloc(HEAPCELL);
|
||||||
|
#ifdef CHECK_WITH_VALGRIND
|
||||||
|
string_pool_count += 1;
|
||||||
|
string_pool = (char **) realloc(string_pool,
|
||||||
|
string_pool_count*sizeof(char **));
|
||||||
|
string_pool[string_pool_count-1] = cell_base_;
|
||||||
|
#endif
|
||||||
cell_ptr_ = 0;
|
cell_ptr_ = 0;
|
||||||
cell_count_ += 1;
|
cell_count_ += 1;
|
||||||
assert(cell_base_ != 0);
|
assert(cell_base_ != 0);
|
||||||
|
|
@ -80,6 +91,22 @@ StringHeapLex::~StringHeapLex()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void StringHeapLex::cleanup()
|
||||||
|
{
|
||||||
|
#ifdef CHECK_WITH_VALGRIND
|
||||||
|
for (unsigned idx = 0 ; idx < string_pool_count ; idx += 1) {
|
||||||
|
free(string_pool[idx]);
|
||||||
|
}
|
||||||
|
free(string_pool);
|
||||||
|
string_pool = NULL;
|
||||||
|
string_pool_count = 0;
|
||||||
|
|
||||||
|
for (unsigned idx = 0 ; idx < HASH_SIZE ; idx += 1) {
|
||||||
|
hash_table_[idx] = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
unsigned StringHeapLex::add_hit_count() const
|
unsigned StringHeapLex::add_hit_count() const
|
||||||
{
|
{
|
||||||
return hit_count_;
|
return hit_count_;
|
||||||
|
|
@ -175,4 +202,3 @@ bool operator < (perm_string a, perm_string b)
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef __StringHeap_H
|
#ifndef __StringHeap_H
|
||||||
#define __StringHeap_H
|
#define __StringHeap_H
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2004 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2002-2009 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -104,6 +104,7 @@ class StringHeapLex : private StringHeap {
|
||||||
|
|
||||||
unsigned add_count() const;
|
unsigned add_count() const;
|
||||||
unsigned add_hit_count() const;
|
unsigned add_hit_count() const;
|
||||||
|
void cleanup();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum { HASH_SIZE = 4096 };
|
enum { HASH_SIZE = 4096 };
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@
|
||||||
CADENCE PLI1 MODULES
|
CADENCE PLI1 MODULES
|
||||||
|
|
||||||
Copyright 2003 Stephen Williams
|
Copyright 2003 Stephen Williams
|
||||||
$Id: cadpli.txt,v 1.2 2003/02/17 00:01:25 steve Exp $
|
|
||||||
|
|
||||||
With the cadpli module, Icarus Verilog is able to load PLI1
|
With the cadpli module, Icarus Verilog is able to load PLI1
|
||||||
applications that were compiled and linked to be dynamic loaded by
|
applications that were compiled and linked to be dynamic loaded by
|
||||||
|
|
@ -34,15 +33,3 @@ the +loadpli1= argument to Verilog-XL.
|
||||||
The integration from this point is seamless. The PLI application
|
The integration from this point is seamless. The PLI application
|
||||||
hardly knows that it is being invoked by Icarus Verilog instead of
|
hardly knows that it is being invoked by Icarus Verilog instead of
|
||||||
Verilog-XL, so operates as it would otherwise.
|
Verilog-XL, so operates as it would otherwise.
|
||||||
|
|
||||||
$Log: cadpli.txt,v $
|
|
||||||
Revision 1.2 2003/02/17 00:01:25 steve
|
|
||||||
Use a variant of ivl_dlfcn to do dynamic loading
|
|
||||||
from within the cadpli module.
|
|
||||||
|
|
||||||
Change the +cadpli flag to -cadpli, to keep the
|
|
||||||
plusargs namespace clear.
|
|
||||||
|
|
||||||
Revision 1.1 2003/02/16 02:44:47 steve
|
|
||||||
Add the cadpli HOWTO.
|
|
||||||
|
|
||||||
|
|
|
||||||
30
compiler.h
30
compiler.h
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef __compiler_H
|
#ifndef __compiler_H
|
||||||
#define __compiler_H
|
#define __compiler_H
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1999-2008 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 1999-2009 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -36,6 +36,12 @@
|
||||||
*/
|
*/
|
||||||
extern unsigned integer_width;
|
extern unsigned integer_width;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is the maximum number of recursive module loops allowed within
|
||||||
|
* a generate block.
|
||||||
|
*/
|
||||||
|
extern unsigned recursive_mod_limit;
|
||||||
|
|
||||||
/* The TIME_WIDTH is the width of time variables. */
|
/* The TIME_WIDTH is the width of time variables. */
|
||||||
#ifndef TIME_WIDTH
|
#ifndef TIME_WIDTH
|
||||||
# define TIME_WIDTH 64
|
# define TIME_WIDTH 64
|
||||||
|
|
@ -76,9 +82,17 @@ extern bool warn_timescale;
|
||||||
/* Warn about legal but questionable module port bindings. */
|
/* Warn about legal but questionable module port bindings. */
|
||||||
extern bool warn_portbinding;
|
extern bool warn_portbinding;
|
||||||
|
|
||||||
|
/* Warn about constant out of bound selects. */
|
||||||
|
extern bool warn_ob_select;
|
||||||
|
|
||||||
/* Warn about structures that may have infinite loops. */
|
/* Warn about structures that may have infinite loops. */
|
||||||
extern bool warn_inf_loop;
|
extern bool warn_inf_loop;
|
||||||
|
|
||||||
|
/* Warn about always @* statements where a part or word select causes
|
||||||
|
sensitivity to an entire vector or array. */
|
||||||
|
extern bool warn_sens_entire_vec;
|
||||||
|
extern bool warn_sens_entire_arr;
|
||||||
|
|
||||||
/* This is true if verbose output is requested. */
|
/* This is true if verbose output is requested. */
|
||||||
extern bool verbose_flag;
|
extern bool verbose_flag;
|
||||||
|
|
||||||
|
|
@ -89,6 +103,12 @@ extern bool debug_elab_pexpr;
|
||||||
extern bool debug_synth2;
|
extern bool debug_synth2;
|
||||||
extern bool debug_optimizer;
|
extern bool debug_optimizer;
|
||||||
|
|
||||||
|
/* Possibly temporary flag to control virtualization of pin arrays */
|
||||||
|
extern bool disable_virtual_pins;
|
||||||
|
|
||||||
|
/* Limit to size of devirtualized arrays */
|
||||||
|
extern unsigned long array_size_limit;
|
||||||
|
|
||||||
/* Path to a directory useful for finding subcomponents. */
|
/* Path to a directory useful for finding subcomponents. */
|
||||||
extern const char*basedir;
|
extern const char*basedir;
|
||||||
|
|
||||||
|
|
@ -101,9 +121,10 @@ extern int build_library_index(const char*path, bool key_case_sensitive);
|
||||||
specific language features. */
|
specific language features. */
|
||||||
enum generation_t {
|
enum generation_t {
|
||||||
GN_VER1995 = 1,
|
GN_VER1995 = 1,
|
||||||
GN_VER2001 = 2,
|
GN_VER2001_NOCONFIG = 2,
|
||||||
GN_VER2005 = 3,
|
GN_VER2001 = 3,
|
||||||
GN_DEFAULT = 3
|
GN_VER2005 = 4,
|
||||||
|
GN_DEFAULT = 4
|
||||||
};
|
};
|
||||||
|
|
||||||
extern generation_t generation_flag;
|
extern generation_t generation_flag;
|
||||||
|
|
@ -189,5 +210,6 @@ struct sfunc_return_type {
|
||||||
|
|
||||||
extern const struct sfunc_return_type* lookup_sys_func(const char*name);
|
extern const struct sfunc_return_type* lookup_sys_func(const char*name);
|
||||||
extern int load_sys_func_table(const char*path);
|
extern int load_sys_func_table(const char*path);
|
||||||
|
extern void cleanup_sys_func_table();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef __config_H /* -*- c++ -*- */
|
#ifndef __config_H /* -*- c++ -*- */
|
||||||
#define __config_H
|
#define __config_H
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2001-2009 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -50,4 +50,10 @@
|
||||||
# include <inttypes.h>
|
# include <inttypes.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Define this if you want to compile vvp with memory freeing and
|
||||||
|
* special valgrind hooks for the memory pools.
|
||||||
|
*/
|
||||||
|
# undef CHECK_WITH_VALGRIND
|
||||||
|
|
||||||
#endif /* __config_H */
|
#endif /* __config_H */
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
#! /bin/sh
|
#! /bin/sh
|
||||||
# Configuration validation subroutine script.
|
# Configuration validation subroutine script.
|
||||||
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
|
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
|
||||||
# 2000, 2001, 2002 Free Software Foundation, Inc.
|
# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
|
||||||
|
# Free Software Foundation, Inc.
|
||||||
|
|
||||||
timestamp='2002-07-03'
|
timestamp='2009-04-17'
|
||||||
|
|
||||||
# This file is (in principle) common to ALL GNU software.
|
# This file is (in principle) common to ALL GNU software.
|
||||||
# The presence of a machine in this file suggests that SOME GNU software
|
# The presence of a machine in this file suggests that SOME GNU software
|
||||||
|
|
@ -21,14 +22,15 @@ timestamp='2002-07-03'
|
||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program; if not, write to the Free Software
|
# along with this program; if not, write to the Free Software
|
||||||
# Foundation, Inc., 59 Temple Place - Suite 330,
|
# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
|
||||||
# Boston, MA 02111-1307, USA.
|
# 02110-1301, USA.
|
||||||
|
#
|
||||||
# As a special exception to the GNU General Public License, if you
|
# As a special exception to the GNU General Public License, if you
|
||||||
# distribute this file as part of a program that contains a
|
# distribute this file as part of a program that contains a
|
||||||
# configuration script generated by Autoconf, you may include it under
|
# configuration script generated by Autoconf, you may include it under
|
||||||
# the same distribution terms that you use for the rest of that program.
|
# the same distribution terms that you use for the rest of that program.
|
||||||
|
|
||||||
|
|
||||||
# Please send patches to <config-patches@gnu.org>. Submit a context
|
# Please send patches to <config-patches@gnu.org>. Submit a context
|
||||||
# diff and a properly formatted ChangeLog entry.
|
# diff and a properly formatted ChangeLog entry.
|
||||||
#
|
#
|
||||||
|
|
@ -70,8 +72,8 @@ Report bugs and patches to <config-patches@gnu.org>."
|
||||||
version="\
|
version="\
|
||||||
GNU config.sub ($timestamp)
|
GNU config.sub ($timestamp)
|
||||||
|
|
||||||
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
|
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
|
||||||
Free Software Foundation, Inc.
|
2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||||
|
|
||||||
This is free software; see the source for copying conditions. There is NO
|
This is free software; see the source for copying conditions. There is NO
|
||||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
|
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
|
||||||
|
|
@ -83,11 +85,11 @@ Try \`$me --help' for more information."
|
||||||
while test $# -gt 0 ; do
|
while test $# -gt 0 ; do
|
||||||
case $1 in
|
case $1 in
|
||||||
--time-stamp | --time* | -t )
|
--time-stamp | --time* | -t )
|
||||||
echo "$timestamp" ; exit 0 ;;
|
echo "$timestamp" ; exit ;;
|
||||||
--version | -v )
|
--version | -v )
|
||||||
echo "$version" ; exit 0 ;;
|
echo "$version" ; exit ;;
|
||||||
--help | --h* | -h )
|
--help | --h* | -h )
|
||||||
echo "$usage"; exit 0 ;;
|
echo "$usage"; exit ;;
|
||||||
-- ) # Stop option processing
|
-- ) # Stop option processing
|
||||||
shift; break ;;
|
shift; break ;;
|
||||||
- ) # Use stdin as input.
|
- ) # Use stdin as input.
|
||||||
|
|
@ -99,7 +101,7 @@ while test $# -gt 0 ; do
|
||||||
*local*)
|
*local*)
|
||||||
# First pass through any local machine types.
|
# First pass through any local machine types.
|
||||||
echo $1
|
echo $1
|
||||||
exit 0;;
|
exit ;;
|
||||||
|
|
||||||
* )
|
* )
|
||||||
break ;;
|
break ;;
|
||||||
|
|
@ -118,7 +120,10 @@ esac
|
||||||
# Here we must recognize all the valid KERNEL-OS combinations.
|
# Here we must recognize all the valid KERNEL-OS combinations.
|
||||||
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
|
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
|
||||||
case $maybe_os in
|
case $maybe_os in
|
||||||
nto-qnx* | linux-gnu* | freebsd*-gnu* | storm-chaos* | os2-emx* | windows32-* | rtmk-nova*)
|
nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
|
||||||
|
uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
|
||||||
|
kopensolaris*-gnu* | \
|
||||||
|
storm-chaos* | os2-emx* | rtmk-nova*)
|
||||||
os=-$maybe_os
|
os=-$maybe_os
|
||||||
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
|
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
|
||||||
;;
|
;;
|
||||||
|
|
@ -144,7 +149,7 @@ case $os in
|
||||||
-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
|
-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
|
||||||
-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
|
-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
|
||||||
-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
|
-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
|
||||||
-apple | -axis)
|
-apple | -axis | -knuth | -cray)
|
||||||
os=
|
os=
|
||||||
basic_machine=$1
|
basic_machine=$1
|
||||||
;;
|
;;
|
||||||
|
|
@ -169,6 +174,10 @@ case $os in
|
||||||
-hiux*)
|
-hiux*)
|
||||||
os=-hiuxwe2
|
os=-hiuxwe2
|
||||||
;;
|
;;
|
||||||
|
-sco6)
|
||||||
|
os=-sco5v6
|
||||||
|
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
|
||||||
|
;;
|
||||||
-sco5)
|
-sco5)
|
||||||
os=-sco3.2v5
|
os=-sco3.2v5
|
||||||
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
|
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
|
||||||
|
|
@ -185,6 +194,10 @@ case $os in
|
||||||
# Don't forget version if it is 3.2v4 or newer.
|
# Don't forget version if it is 3.2v4 or newer.
|
||||||
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
|
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
|
||||||
;;
|
;;
|
||||||
|
-sco5v6*)
|
||||||
|
# Don't forget version if it is 3.2v4 or newer.
|
||||||
|
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
|
||||||
|
;;
|
||||||
-sco*)
|
-sco*)
|
||||||
os=-sco3.2v2
|
os=-sco3.2v2
|
||||||
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
|
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
|
||||||
|
|
@ -228,40 +241,57 @@ case $basic_machine in
|
||||||
| a29k \
|
| a29k \
|
||||||
| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
|
| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
|
||||||
| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
|
| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
|
||||||
| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
|
| am33_2.0 \
|
||||||
|
| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
|
||||||
|
| bfin \
|
||||||
| c4x | clipper \
|
| c4x | clipper \
|
||||||
| d10v | d30v | dlx | dsp16xx \
|
| d10v | d30v | dlx | dsp16xx \
|
||||||
| fr30 | frv \
|
| fido | fr30 | frv \
|
||||||
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
|
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
|
||||||
| i370 | i860 | i960 | ia64 \
|
| i370 | i860 | i960 | ia64 \
|
||||||
| ip2k \
|
| ip2k | iq2000 \
|
||||||
| m32r | m68000 | m68k | m88k | mcore \
|
| lm32 \
|
||||||
|
| m32c | m32r | m32rle | m68000 | m68k | m88k \
|
||||||
|
| maxq | mb | microblaze | mcore | mep | metag \
|
||||||
| mips | mipsbe | mipseb | mipsel | mipsle \
|
| mips | mipsbe | mipseb | mipsel | mipsle \
|
||||||
| mips16 \
|
| mips16 \
|
||||||
| mips64 | mips64el \
|
| mips64 | mips64el \
|
||||||
|
| mips64octeon | mips64octeonel \
|
||||||
| mips64orion | mips64orionel \
|
| mips64orion | mips64orionel \
|
||||||
|
| mips64r5900 | mips64r5900el \
|
||||||
|
| mips64vr | mips64vrel \
|
||||||
| mips64vr4100 | mips64vr4100el \
|
| mips64vr4100 | mips64vr4100el \
|
||||||
| mips64vr4300 | mips64vr4300el \
|
| mips64vr4300 | mips64vr4300el \
|
||||||
| mips64vr5000 | mips64vr5000el \
|
| mips64vr5000 | mips64vr5000el \
|
||||||
|
| mips64vr5900 | mips64vr5900el \
|
||||||
| mipsisa32 | mipsisa32el \
|
| mipsisa32 | mipsisa32el \
|
||||||
|
| mipsisa32r2 | mipsisa32r2el \
|
||||||
| mipsisa64 | mipsisa64el \
|
| mipsisa64 | mipsisa64el \
|
||||||
|
| mipsisa64r2 | mipsisa64r2el \
|
||||||
| mipsisa64sb1 | mipsisa64sb1el \
|
| mipsisa64sb1 | mipsisa64sb1el \
|
||||||
|
| mipsisa64sr71k | mipsisa64sr71kel \
|
||||||
| mipstx39 | mipstx39el \
|
| mipstx39 | mipstx39el \
|
||||||
| mn10200 | mn10300 \
|
| mn10200 | mn10300 \
|
||||||
|
| moxie \
|
||||||
|
| mt \
|
||||||
|
| msp430 \
|
||||||
|
| nios | nios2 \
|
||||||
| ns16k | ns32k \
|
| ns16k | ns32k \
|
||||||
| openrisc | or32 \
|
| or32 \
|
||||||
| pdp10 | pdp11 | pj | pjl \
|
| pdp10 | pdp11 | pj | pjl \
|
||||||
| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
|
| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
|
||||||
| pyramid \
|
| pyramid \
|
||||||
| sh | sh[1234] | sh3e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
|
| score \
|
||||||
|
| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
|
||||||
| sh64 | sh64le \
|
| sh64 | sh64le \
|
||||||
| sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \
|
| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
|
||||||
| strongarm \
|
| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
|
||||||
| tahoe | thumb | tic80 | tron \
|
| spu | strongarm \
|
||||||
|
| tahoe | thumb | tic4x | tic80 | tron \
|
||||||
| v850 | v850e \
|
| v850 | v850e \
|
||||||
| we32k \
|
| we32k \
|
||||||
| x86 | xscale | xstormy16 | xtensa \
|
| x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \
|
||||||
| z8k)
|
| z8k | z80)
|
||||||
basic_machine=$basic_machine-unknown
|
basic_machine=$basic_machine-unknown
|
||||||
;;
|
;;
|
||||||
m6811 | m68hc11 | m6812 | m68hc12)
|
m6811 | m68hc11 | m6812 | m68hc12)
|
||||||
|
|
@ -271,6 +301,9 @@ case $basic_machine in
|
||||||
;;
|
;;
|
||||||
m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
|
m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
|
||||||
;;
|
;;
|
||||||
|
ms1)
|
||||||
|
basic_machine=mt-unknown
|
||||||
|
;;
|
||||||
|
|
||||||
# We use `pc' rather than `unknown'
|
# We use `pc' rather than `unknown'
|
||||||
# because (1) that's what they normally are, and
|
# because (1) that's what they normally are, and
|
||||||
|
|
@ -290,48 +323,67 @@ case $basic_machine in
|
||||||
| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
|
| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
|
||||||
| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
|
| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
|
||||||
| arm-* | armbe-* | armle-* | armeb-* | armv*-* \
|
| arm-* | armbe-* | armle-* | armeb-* | armv*-* \
|
||||||
| avr-* \
|
| avr-* | avr32-* \
|
||||||
| bs2000-* \
|
| bfin-* | bs2000-* \
|
||||||
| c[123]* | c30-* | [cjt]90-* | c54x-* \
|
| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
|
||||||
| clipper-* | cydra-* \
|
| clipper-* | craynv-* | cydra-* \
|
||||||
| d10v-* | d30v-* | dlx-* \
|
| d10v-* | d30v-* | dlx-* \
|
||||||
| elxsi-* \
|
| elxsi-* \
|
||||||
| f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \
|
| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
|
||||||
| h8300-* | h8500-* \
|
| h8300-* | h8500-* \
|
||||||
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
|
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
|
||||||
| i*86-* | i860-* | i960-* | ia64-* \
|
| i*86-* | i860-* | i960-* | ia64-* \
|
||||||
| ip2k-* \
|
| ip2k-* | iq2000-* \
|
||||||
| m32r-* \
|
| lm32-* \
|
||||||
|
| m32c-* | m32r-* | m32rle-* \
|
||||||
| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
|
| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
|
||||||
| m88110-* | m88k-* | mcore-* \
|
| m88110-* | m88k-* | maxq-* | mcore-* | metag-* \
|
||||||
| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
|
| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
|
||||||
| mips16-* \
|
| mips16-* \
|
||||||
| mips64-* | mips64el-* \
|
| mips64-* | mips64el-* \
|
||||||
|
| mips64octeon-* | mips64octeonel-* \
|
||||||
| mips64orion-* | mips64orionel-* \
|
| mips64orion-* | mips64orionel-* \
|
||||||
|
| mips64r5900-* | mips64r5900el-* \
|
||||||
|
| mips64vr-* | mips64vrel-* \
|
||||||
| mips64vr4100-* | mips64vr4100el-* \
|
| mips64vr4100-* | mips64vr4100el-* \
|
||||||
| mips64vr4300-* | mips64vr4300el-* \
|
| mips64vr4300-* | mips64vr4300el-* \
|
||||||
| mips64vr5000-* | mips64vr5000el-* \
|
| mips64vr5000-* | mips64vr5000el-* \
|
||||||
|
| mips64vr5900-* | mips64vr5900el-* \
|
||||||
| mipsisa32-* | mipsisa32el-* \
|
| mipsisa32-* | mipsisa32el-* \
|
||||||
|
| mipsisa32r2-* | mipsisa32r2el-* \
|
||||||
| mipsisa64-* | mipsisa64el-* \
|
| mipsisa64-* | mipsisa64el-* \
|
||||||
|
| mipsisa64r2-* | mipsisa64r2el-* \
|
||||||
| mipsisa64sb1-* | mipsisa64sb1el-* \
|
| mipsisa64sb1-* | mipsisa64sb1el-* \
|
||||||
| mipstx39 | mipstx39el \
|
| mipsisa64sr71k-* | mipsisa64sr71kel-* \
|
||||||
|
| mipstx39-* | mipstx39el-* \
|
||||||
|
| mmix-* \
|
||||||
|
| mt-* \
|
||||||
|
| msp430-* \
|
||||||
|
| nios-* | nios2-* \
|
||||||
| none-* | np1-* | ns16k-* | ns32k-* \
|
| none-* | np1-* | ns16k-* | ns32k-* \
|
||||||
| orion-* \
|
| orion-* \
|
||||||
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
|
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
|
||||||
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
|
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
|
||||||
| pyramid-* \
|
| pyramid-* \
|
||||||
| romp-* | rs6000-* \
|
| romp-* | rs6000-* \
|
||||||
| sh-* | sh[1234]-* | sh3e-* | sh[34]eb-* | shbe-* \
|
| sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
|
||||||
| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
|
| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
|
||||||
| sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \
|
| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
|
||||||
| sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
|
| sparclite-* \
|
||||||
| tahoe-* | thumb-* | tic30-* | tic54x-* | tic80-* | tron-* \
|
| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
|
||||||
|
| tahoe-* | thumb-* \
|
||||||
|
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* | tile-* \
|
||||||
|
| tron-* \
|
||||||
| v850-* | v850e-* | vax-* \
|
| v850-* | v850e-* | vax-* \
|
||||||
| we32k-* \
|
| we32k-* \
|
||||||
| x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \
|
| x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \
|
||||||
| xtensa-* \
|
| xstormy16-* | xtensa*-* \
|
||||||
| ymp-* \
|
| ymp-* \
|
||||||
| z8k-*)
|
| z8k-* | z80-*)
|
||||||
|
;;
|
||||||
|
# Recognize the basic CPU types without company name, with glob match.
|
||||||
|
xtensa*)
|
||||||
|
basic_machine=$basic_machine-unknown
|
||||||
;;
|
;;
|
||||||
# Recognize the various machine names and aliases which stand
|
# Recognize the various machine names and aliases which stand
|
||||||
# for a CPU type and a company and sometimes even an OS.
|
# for a CPU type and a company and sometimes even an OS.
|
||||||
|
|
@ -349,6 +401,9 @@ case $basic_machine in
|
||||||
basic_machine=a29k-amd
|
basic_machine=a29k-amd
|
||||||
os=-udi
|
os=-udi
|
||||||
;;
|
;;
|
||||||
|
abacus)
|
||||||
|
basic_machine=abacus-unknown
|
||||||
|
;;
|
||||||
adobe68k)
|
adobe68k)
|
||||||
basic_machine=m68010-adobe
|
basic_machine=m68010-adobe
|
||||||
os=-scout
|
os=-scout
|
||||||
|
|
@ -363,6 +418,12 @@ case $basic_machine in
|
||||||
basic_machine=a29k-none
|
basic_machine=a29k-none
|
||||||
os=-bsd
|
os=-bsd
|
||||||
;;
|
;;
|
||||||
|
amd64)
|
||||||
|
basic_machine=x86_64-pc
|
||||||
|
;;
|
||||||
|
amd64-*)
|
||||||
|
basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||||
|
;;
|
||||||
amdahl)
|
amdahl)
|
||||||
basic_machine=580-amdahl
|
basic_machine=580-amdahl
|
||||||
os=-sysv
|
os=-sysv
|
||||||
|
|
@ -386,6 +447,10 @@ case $basic_machine in
|
||||||
basic_machine=m68k-apollo
|
basic_machine=m68k-apollo
|
||||||
os=-bsd
|
os=-bsd
|
||||||
;;
|
;;
|
||||||
|
aros)
|
||||||
|
basic_machine=i386-pc
|
||||||
|
os=-aros
|
||||||
|
;;
|
||||||
aux)
|
aux)
|
||||||
basic_machine=m68k-apple
|
basic_machine=m68k-apple
|
||||||
os=-aux
|
os=-aux
|
||||||
|
|
@ -394,10 +459,22 @@ case $basic_machine in
|
||||||
basic_machine=ns32k-sequent
|
basic_machine=ns32k-sequent
|
||||||
os=-dynix
|
os=-dynix
|
||||||
;;
|
;;
|
||||||
|
blackfin)
|
||||||
|
basic_machine=bfin-unknown
|
||||||
|
os=-linux
|
||||||
|
;;
|
||||||
|
blackfin-*)
|
||||||
|
basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||||
|
os=-linux
|
||||||
|
;;
|
||||||
c90)
|
c90)
|
||||||
basic_machine=c90-cray
|
basic_machine=c90-cray
|
||||||
os=-unicos
|
os=-unicos
|
||||||
;;
|
;;
|
||||||
|
cegcc)
|
||||||
|
basic_machine=arm-unknown
|
||||||
|
os=-cegcc
|
||||||
|
;;
|
||||||
convex-c1)
|
convex-c1)
|
||||||
basic_machine=c1-convex
|
basic_machine=c1-convex
|
||||||
os=-bsd
|
os=-bsd
|
||||||
|
|
@ -422,12 +499,27 @@ case $basic_machine in
|
||||||
basic_machine=j90-cray
|
basic_machine=j90-cray
|
||||||
os=-unicos
|
os=-unicos
|
||||||
;;
|
;;
|
||||||
|
craynv)
|
||||||
|
basic_machine=craynv-cray
|
||||||
|
os=-unicosmp
|
||||||
|
;;
|
||||||
|
cr16)
|
||||||
|
basic_machine=cr16-unknown
|
||||||
|
os=-elf
|
||||||
|
;;
|
||||||
crds | unos)
|
crds | unos)
|
||||||
basic_machine=m68k-crds
|
basic_machine=m68k-crds
|
||||||
;;
|
;;
|
||||||
|
crisv32 | crisv32-* | etraxfs*)
|
||||||
|
basic_machine=crisv32-axis
|
||||||
|
;;
|
||||||
cris | cris-* | etrax*)
|
cris | cris-* | etrax*)
|
||||||
basic_machine=cris-axis
|
basic_machine=cris-axis
|
||||||
;;
|
;;
|
||||||
|
crx)
|
||||||
|
basic_machine=crx-unknown
|
||||||
|
os=-elf
|
||||||
|
;;
|
||||||
da30 | da30-*)
|
da30 | da30-*)
|
||||||
basic_machine=m68k-da30
|
basic_machine=m68k-da30
|
||||||
;;
|
;;
|
||||||
|
|
@ -450,6 +542,14 @@ case $basic_machine in
|
||||||
basic_machine=m88k-motorola
|
basic_machine=m88k-motorola
|
||||||
os=-sysv3
|
os=-sysv3
|
||||||
;;
|
;;
|
||||||
|
dicos)
|
||||||
|
basic_machine=i686-pc
|
||||||
|
os=-dicos
|
||||||
|
;;
|
||||||
|
djgpp)
|
||||||
|
basic_machine=i586-pc
|
||||||
|
os=-msdosdjgpp
|
||||||
|
;;
|
||||||
dpx20 | dpx20-*)
|
dpx20 | dpx20-*)
|
||||||
basic_machine=rs6000-bull
|
basic_machine=rs6000-bull
|
||||||
os=-bosx
|
os=-bosx
|
||||||
|
|
@ -600,6 +700,14 @@ case $basic_machine in
|
||||||
basic_machine=m68k-isi
|
basic_machine=m68k-isi
|
||||||
os=-sysv
|
os=-sysv
|
||||||
;;
|
;;
|
||||||
|
m68knommu)
|
||||||
|
basic_machine=m68k-unknown
|
||||||
|
os=-linux
|
||||||
|
;;
|
||||||
|
m68knommu-*)
|
||||||
|
basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||||
|
os=-linux
|
||||||
|
;;
|
||||||
m88k-omron*)
|
m88k-omron*)
|
||||||
basic_machine=m88k-omron
|
basic_machine=m88k-omron
|
||||||
;;
|
;;
|
||||||
|
|
@ -615,6 +723,10 @@ case $basic_machine in
|
||||||
basic_machine=i386-pc
|
basic_machine=i386-pc
|
||||||
os=-mingw32
|
os=-mingw32
|
||||||
;;
|
;;
|
||||||
|
mingw32ce)
|
||||||
|
basic_machine=arm-unknown
|
||||||
|
os=-mingw32ce
|
||||||
|
;;
|
||||||
miniframe)
|
miniframe)
|
||||||
basic_machine=m68000-convergent
|
basic_machine=m68000-convergent
|
||||||
;;
|
;;
|
||||||
|
|
@ -628,10 +740,6 @@ case $basic_machine in
|
||||||
mips3*)
|
mips3*)
|
||||||
basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
|
basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
|
||||||
;;
|
;;
|
||||||
mmix*)
|
|
||||||
basic_machine=mmix-knuth
|
|
||||||
os=-mmixware
|
|
||||||
;;
|
|
||||||
monitor)
|
monitor)
|
||||||
basic_machine=m68k-rom68k
|
basic_machine=m68k-rom68k
|
||||||
os=-coff
|
os=-coff
|
||||||
|
|
@ -644,6 +752,9 @@ case $basic_machine in
|
||||||
basic_machine=i386-pc
|
basic_machine=i386-pc
|
||||||
os=-msdos
|
os=-msdos
|
||||||
;;
|
;;
|
||||||
|
ms1-*)
|
||||||
|
basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
|
||||||
|
;;
|
||||||
mvs)
|
mvs)
|
||||||
basic_machine=i370-ibm
|
basic_machine=i370-ibm
|
||||||
os=-mvs
|
os=-mvs
|
||||||
|
|
@ -719,9 +830,12 @@ case $basic_machine in
|
||||||
basic_machine=hppa1.1-oki
|
basic_machine=hppa1.1-oki
|
||||||
os=-proelf
|
os=-proelf
|
||||||
;;
|
;;
|
||||||
or32 | or32-*)
|
openrisc | openrisc-*)
|
||||||
basic_machine=or32-unknown
|
basic_machine=or32-unknown
|
||||||
os=-coff
|
;;
|
||||||
|
os400)
|
||||||
|
basic_machine=powerpc-ibm
|
||||||
|
os=-os400
|
||||||
;;
|
;;
|
||||||
OSE68000 | ose68000)
|
OSE68000 | ose68000)
|
||||||
basic_machine=m68000-ericsson
|
basic_machine=m68000-ericsson
|
||||||
|
|
@ -739,55 +853,75 @@ case $basic_machine in
|
||||||
basic_machine=i860-intel
|
basic_machine=i860-intel
|
||||||
os=-osf
|
os=-osf
|
||||||
;;
|
;;
|
||||||
|
parisc)
|
||||||
|
basic_machine=hppa-unknown
|
||||||
|
os=-linux
|
||||||
|
;;
|
||||||
|
parisc-*)
|
||||||
|
basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||||
|
os=-linux
|
||||||
|
;;
|
||||||
pbd)
|
pbd)
|
||||||
basic_machine=sparc-tti
|
basic_machine=sparc-tti
|
||||||
;;
|
;;
|
||||||
pbb)
|
pbb)
|
||||||
basic_machine=m68k-tti
|
basic_machine=m68k-tti
|
||||||
;;
|
;;
|
||||||
pc532 | pc532-*)
|
pc532 | pc532-*)
|
||||||
basic_machine=ns32k-pc532
|
basic_machine=ns32k-pc532
|
||||||
;;
|
;;
|
||||||
|
pc98)
|
||||||
|
basic_machine=i386-pc
|
||||||
|
;;
|
||||||
|
pc98-*)
|
||||||
|
basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||||
|
;;
|
||||||
pentium | p5 | k5 | k6 | nexgen | viac3)
|
pentium | p5 | k5 | k6 | nexgen | viac3)
|
||||||
basic_machine=i586-pc
|
basic_machine=i586-pc
|
||||||
;;
|
;;
|
||||||
pentiumpro | p6 | 6x86 | athlon)
|
pentiumpro | p6 | 6x86 | athlon | athlon_*)
|
||||||
basic_machine=i686-pc
|
basic_machine=i686-pc
|
||||||
;;
|
;;
|
||||||
pentiumii | pentium2)
|
pentiumii | pentium2 | pentiumiii | pentium3)
|
||||||
basic_machine=i686-pc
|
basic_machine=i686-pc
|
||||||
;;
|
;;
|
||||||
|
pentium4)
|
||||||
|
basic_machine=i786-pc
|
||||||
|
;;
|
||||||
pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
|
pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
|
||||||
basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
|
basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||||
;;
|
;;
|
||||||
pentiumpro-* | p6-* | 6x86-* | athlon-*)
|
pentiumpro-* | p6-* | 6x86-* | athlon-*)
|
||||||
basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
|
basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||||
;;
|
;;
|
||||||
pentiumii-* | pentium2-*)
|
pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
|
||||||
basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
|
basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||||
;;
|
;;
|
||||||
|
pentium4-*)
|
||||||
|
basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||||
|
;;
|
||||||
pn)
|
pn)
|
||||||
basic_machine=pn-gould
|
basic_machine=pn-gould
|
||||||
;;
|
;;
|
||||||
power) basic_machine=power-ibm
|
power) basic_machine=power-ibm
|
||||||
;;
|
;;
|
||||||
ppc) basic_machine=powerpc-unknown
|
ppc) basic_machine=powerpc-unknown
|
||||||
;;
|
;;
|
||||||
ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
|
ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||||
;;
|
;;
|
||||||
ppcle | powerpclittle | ppc-le | powerpc-little)
|
ppcle | powerpclittle | ppc-le | powerpc-little)
|
||||||
basic_machine=powerpcle-unknown
|
basic_machine=powerpcle-unknown
|
||||||
;;
|
;;
|
||||||
ppcle-* | powerpclittle-*)
|
ppcle-* | powerpclittle-*)
|
||||||
basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
|
basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||||
;;
|
;;
|
||||||
ppc64) basic_machine=powerpc64-unknown
|
ppc64) basic_machine=powerpc64-unknown
|
||||||
;;
|
;;
|
||||||
ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
|
ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||||
;;
|
;;
|
||||||
ppc64le | powerpc64little | ppc64-le | powerpc64-little)
|
ppc64le | powerpc64little | ppc64-le | powerpc64-little)
|
||||||
basic_machine=powerpc64le-unknown
|
basic_machine=powerpc64le-unknown
|
||||||
;;
|
;;
|
||||||
ppc64le-* | powerpc64little-*)
|
ppc64le-* | powerpc64little-*)
|
||||||
basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
|
basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||||
;;
|
;;
|
||||||
|
|
@ -798,6 +932,10 @@ case $basic_machine in
|
||||||
basic_machine=i586-unknown
|
basic_machine=i586-unknown
|
||||||
os=-pw32
|
os=-pw32
|
||||||
;;
|
;;
|
||||||
|
rdos)
|
||||||
|
basic_machine=i386-pc
|
||||||
|
os=-rdos
|
||||||
|
;;
|
||||||
rom68k)
|
rom68k)
|
||||||
basic_machine=m68k-rom68k
|
basic_machine=m68k-rom68k
|
||||||
os=-coff
|
os=-coff
|
||||||
|
|
@ -818,6 +956,20 @@ case $basic_machine in
|
||||||
basic_machine=a29k-amd
|
basic_machine=a29k-amd
|
||||||
os=-udi
|
os=-udi
|
||||||
;;
|
;;
|
||||||
|
sb1)
|
||||||
|
basic_machine=mipsisa64sb1-unknown
|
||||||
|
;;
|
||||||
|
sb1el)
|
||||||
|
basic_machine=mipsisa64sb1el-unknown
|
||||||
|
;;
|
||||||
|
sde)
|
||||||
|
basic_machine=mipsisa32-sde
|
||||||
|
os=-elf
|
||||||
|
;;
|
||||||
|
sei)
|
||||||
|
basic_machine=mips-sei
|
||||||
|
os=-seiux
|
||||||
|
;;
|
||||||
sequent)
|
sequent)
|
||||||
basic_machine=i386-sequent
|
basic_machine=i386-sequent
|
||||||
;;
|
;;
|
||||||
|
|
@ -825,6 +977,12 @@ case $basic_machine in
|
||||||
basic_machine=sh-hitachi
|
basic_machine=sh-hitachi
|
||||||
os=-hms
|
os=-hms
|
||||||
;;
|
;;
|
||||||
|
sh5el)
|
||||||
|
basic_machine=sh5le-unknown
|
||||||
|
;;
|
||||||
|
sh64)
|
||||||
|
basic_machine=sh64-unknown
|
||||||
|
;;
|
||||||
sparclite-wrs | simso-wrs)
|
sparclite-wrs | simso-wrs)
|
||||||
basic_machine=sparclite-wrs
|
basic_machine=sparclite-wrs
|
||||||
os=-vxworks
|
os=-vxworks
|
||||||
|
|
@ -883,7 +1041,7 @@ case $basic_machine in
|
||||||
sun386 | sun386i | roadrunner)
|
sun386 | sun386i | roadrunner)
|
||||||
basic_machine=i386-sun
|
basic_machine=i386-sun
|
||||||
;;
|
;;
|
||||||
sv1)
|
sv1)
|
||||||
basic_machine=sv1-cray
|
basic_machine=sv1-cray
|
||||||
os=-unicos
|
os=-unicos
|
||||||
;;
|
;;
|
||||||
|
|
@ -891,10 +1049,6 @@ case $basic_machine in
|
||||||
basic_machine=i386-sequent
|
basic_machine=i386-sequent
|
||||||
os=-dynix
|
os=-dynix
|
||||||
;;
|
;;
|
||||||
t3d)
|
|
||||||
basic_machine=alpha-cray
|
|
||||||
os=-unicos
|
|
||||||
;;
|
|
||||||
t3e)
|
t3e)
|
||||||
basic_machine=alphaev5-cray
|
basic_machine=alphaev5-cray
|
||||||
os=-unicos
|
os=-unicos
|
||||||
|
|
@ -907,6 +1061,18 @@ case $basic_machine in
|
||||||
basic_machine=tic54x-unknown
|
basic_machine=tic54x-unknown
|
||||||
os=-coff
|
os=-coff
|
||||||
;;
|
;;
|
||||||
|
tic55x | c55x*)
|
||||||
|
basic_machine=tic55x-unknown
|
||||||
|
os=-coff
|
||||||
|
;;
|
||||||
|
tic6x | c6x*)
|
||||||
|
basic_machine=tic6x-unknown
|
||||||
|
os=-coff
|
||||||
|
;;
|
||||||
|
tile*)
|
||||||
|
basic_machine=tile-unknown
|
||||||
|
os=-linux-gnu
|
||||||
|
;;
|
||||||
tx39)
|
tx39)
|
||||||
basic_machine=mipstx39-unknown
|
basic_machine=mipstx39-unknown
|
||||||
;;
|
;;
|
||||||
|
|
@ -920,6 +1086,10 @@ case $basic_machine in
|
||||||
tower | tower-32)
|
tower | tower-32)
|
||||||
basic_machine=m68k-ncr
|
basic_machine=m68k-ncr
|
||||||
;;
|
;;
|
||||||
|
tpf)
|
||||||
|
basic_machine=s390x-ibm
|
||||||
|
os=-tpf
|
||||||
|
;;
|
||||||
udi29k)
|
udi29k)
|
||||||
basic_machine=a29k-amd
|
basic_machine=a29k-amd
|
||||||
os=-udi
|
os=-udi
|
||||||
|
|
@ -941,8 +1111,8 @@ case $basic_machine in
|
||||||
os=-vms
|
os=-vms
|
||||||
;;
|
;;
|
||||||
vpp*|vx|vx-*)
|
vpp*|vx|vx-*)
|
||||||
basic_machine=f301-fujitsu
|
basic_machine=f301-fujitsu
|
||||||
;;
|
;;
|
||||||
vxworks960)
|
vxworks960)
|
||||||
basic_machine=i960-wrs
|
basic_machine=i960-wrs
|
||||||
os=-vxworks
|
os=-vxworks
|
||||||
|
|
@ -963,11 +1133,11 @@ case $basic_machine in
|
||||||
basic_machine=hppa1.1-winbond
|
basic_machine=hppa1.1-winbond
|
||||||
os=-proelf
|
os=-proelf
|
||||||
;;
|
;;
|
||||||
windows32)
|
xbox)
|
||||||
basic_machine=i386-pc
|
basic_machine=i686-pc
|
||||||
os=-windows32-msvcrt
|
os=-mingw32
|
||||||
;;
|
;;
|
||||||
xps | xps100)
|
xps | xps100)
|
||||||
basic_machine=xps100-honeywell
|
basic_machine=xps100-honeywell
|
||||||
;;
|
;;
|
||||||
ymp)
|
ymp)
|
||||||
|
|
@ -978,6 +1148,10 @@ case $basic_machine in
|
||||||
basic_machine=z8k-unknown
|
basic_machine=z8k-unknown
|
||||||
os=-sim
|
os=-sim
|
||||||
;;
|
;;
|
||||||
|
z80-*-coff)
|
||||||
|
basic_machine=z80-unknown
|
||||||
|
os=-sim
|
||||||
|
;;
|
||||||
none)
|
none)
|
||||||
basic_machine=none-none
|
basic_machine=none-none
|
||||||
os=-none
|
os=-none
|
||||||
|
|
@ -997,6 +1171,9 @@ case $basic_machine in
|
||||||
romp)
|
romp)
|
||||||
basic_machine=romp-ibm
|
basic_machine=romp-ibm
|
||||||
;;
|
;;
|
||||||
|
mmix)
|
||||||
|
basic_machine=mmix-knuth
|
||||||
|
;;
|
||||||
rs6000)
|
rs6000)
|
||||||
basic_machine=rs6000-ibm
|
basic_machine=rs6000-ibm
|
||||||
;;
|
;;
|
||||||
|
|
@ -1013,16 +1190,13 @@ case $basic_machine in
|
||||||
we32k)
|
we32k)
|
||||||
basic_machine=we32k-att
|
basic_machine=we32k-att
|
||||||
;;
|
;;
|
||||||
sh3 | sh4 | sh3eb | sh4eb | sh[1234]le | sh3ele)
|
sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele)
|
||||||
basic_machine=sh-unknown
|
basic_machine=sh-unknown
|
||||||
;;
|
;;
|
||||||
sh64)
|
sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
|
||||||
basic_machine=sh64-unknown
|
|
||||||
;;
|
|
||||||
sparc | sparcv9 | sparcv9b)
|
|
||||||
basic_machine=sparc-sun
|
basic_machine=sparc-sun
|
||||||
;;
|
;;
|
||||||
cydra)
|
cydra)
|
||||||
basic_machine=cydra-cydrome
|
basic_machine=cydra-cydrome
|
||||||
;;
|
;;
|
||||||
orion)
|
orion)
|
||||||
|
|
@ -1037,10 +1211,6 @@ case $basic_machine in
|
||||||
pmac | pmac-mpw)
|
pmac | pmac-mpw)
|
||||||
basic_machine=powerpc-apple
|
basic_machine=powerpc-apple
|
||||||
;;
|
;;
|
||||||
c4x*)
|
|
||||||
basic_machine=c4x-none
|
|
||||||
os=-coff
|
|
||||||
;;
|
|
||||||
*-unknown)
|
*-unknown)
|
||||||
# Make sure to match an already-canonicalized machine name.
|
# Make sure to match an already-canonicalized machine name.
|
||||||
;;
|
;;
|
||||||
|
|
@ -1092,22 +1262,28 @@ case $os in
|
||||||
-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
|
-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
|
||||||
| -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
|
| -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
|
||||||
| -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
|
| -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
|
||||||
|
| -kopensolaris* \
|
||||||
| -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
|
| -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
|
||||||
| -aos* \
|
| -aos* | -aros* \
|
||||||
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
|
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
|
||||||
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
|
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
|
||||||
| -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \
|
| -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
|
||||||
| -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
|
| -openbsd* | -solidbsd* \
|
||||||
|
| -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
|
||||||
|
| -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
|
||||||
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
|
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
|
||||||
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
|
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
|
||||||
| -chorusos* | -chorusrdb* \
|
| -chorusos* | -chorusrdb* | -cegcc* \
|
||||||
| -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
|
| -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
|
||||||
| -mingw32* | -linux* | -uxpv* | -beos* | -mpeix* | -udk* \
|
| -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
|
||||||
| -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \
|
| -uxpv* | -beos* | -mpeix* | -udk* \
|
||||||
|
| -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
|
||||||
| -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
|
| -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
|
||||||
| -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
|
| -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
|
||||||
| -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
|
| -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
|
||||||
| -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* | -powermax*)
|
| -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
|
||||||
|
| -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
|
||||||
|
| -skyos* | -haiku* | -rdos* | -toppers* | -drops*)
|
||||||
# Remember, each alternative MUST END IN *, to match a version number.
|
# Remember, each alternative MUST END IN *, to match a version number.
|
||||||
;;
|
;;
|
||||||
-qnx*)
|
-qnx*)
|
||||||
|
|
@ -1119,16 +1295,24 @@ case $os in
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
;;
|
;;
|
||||||
|
-nto-qnx*)
|
||||||
|
;;
|
||||||
-nto*)
|
-nto*)
|
||||||
os=-nto-qnx
|
os=`echo $os | sed -e 's|nto|nto-qnx|'`
|
||||||
;;
|
;;
|
||||||
-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
|
-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
|
||||||
| -windows* | -osx | -abug | -netware* | -os9* | -beos* \
|
| -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
|
||||||
| -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
|
| -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
|
||||||
;;
|
;;
|
||||||
-mac*)
|
-mac*)
|
||||||
os=`echo $os | sed -e 's|mac|macos|'`
|
os=`echo $os | sed -e 's|mac|macos|'`
|
||||||
;;
|
;;
|
||||||
|
-linux-dietlibc)
|
||||||
|
os=-linux-dietlibc
|
||||||
|
;;
|
||||||
|
-linux*)
|
||||||
|
os=`echo $os | sed -e 's|linux|linux-gnu|'`
|
||||||
|
;;
|
||||||
-sunos5*)
|
-sunos5*)
|
||||||
os=`echo $os | sed -e 's|sunos5|solaris2|'`
|
os=`echo $os | sed -e 's|sunos5|solaris2|'`
|
||||||
;;
|
;;
|
||||||
|
|
@ -1138,6 +1322,9 @@ case $os in
|
||||||
-opened*)
|
-opened*)
|
||||||
os=-openedition
|
os=-openedition
|
||||||
;;
|
;;
|
||||||
|
-os400*)
|
||||||
|
os=-os400
|
||||||
|
;;
|
||||||
-wince*)
|
-wince*)
|
||||||
os=-wince
|
os=-wince
|
||||||
;;
|
;;
|
||||||
|
|
@ -1159,6 +1346,9 @@ case $os in
|
||||||
-atheos*)
|
-atheos*)
|
||||||
os=-atheos
|
os=-atheos
|
||||||
;;
|
;;
|
||||||
|
-syllable*)
|
||||||
|
os=-syllable
|
||||||
|
;;
|
||||||
-386bsd)
|
-386bsd)
|
||||||
os=-bsd
|
os=-bsd
|
||||||
;;
|
;;
|
||||||
|
|
@ -1169,7 +1359,7 @@ case $os in
|
||||||
os=-rtmk-nova
|
os=-rtmk-nova
|
||||||
;;
|
;;
|
||||||
-ns2 )
|
-ns2 )
|
||||||
os=-nextstep2
|
os=-nextstep2
|
||||||
;;
|
;;
|
||||||
-nsk*)
|
-nsk*)
|
||||||
os=-nsk
|
os=-nsk
|
||||||
|
|
@ -1181,6 +1371,9 @@ case $os in
|
||||||
-sinix*)
|
-sinix*)
|
||||||
os=-sysv4
|
os=-sysv4
|
||||||
;;
|
;;
|
||||||
|
-tpf*)
|
||||||
|
os=-tpf
|
||||||
|
;;
|
||||||
-triton*)
|
-triton*)
|
||||||
os=-sysv3
|
os=-sysv3
|
||||||
;;
|
;;
|
||||||
|
|
@ -1208,8 +1401,20 @@ case $os in
|
||||||
-xenix)
|
-xenix)
|
||||||
os=-xenix
|
os=-xenix
|
||||||
;;
|
;;
|
||||||
-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
|
-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
|
||||||
os=-mint
|
os=-mint
|
||||||
|
;;
|
||||||
|
-aros*)
|
||||||
|
os=-aros
|
||||||
|
;;
|
||||||
|
-kaos*)
|
||||||
|
os=-kaos
|
||||||
|
;;
|
||||||
|
-zvmoe)
|
||||||
|
os=-zvmoe
|
||||||
|
;;
|
||||||
|
-dicos*)
|
||||||
|
os=-dicos
|
||||||
;;
|
;;
|
||||||
-none)
|
-none)
|
||||||
;;
|
;;
|
||||||
|
|
@ -1233,6 +1438,12 @@ else
|
||||||
# system, and we'll never get to this point.
|
# system, and we'll never get to this point.
|
||||||
|
|
||||||
case $basic_machine in
|
case $basic_machine in
|
||||||
|
score-*)
|
||||||
|
os=-elf
|
||||||
|
;;
|
||||||
|
spu-*)
|
||||||
|
os=-elf
|
||||||
|
;;
|
||||||
*-acorn)
|
*-acorn)
|
||||||
os=-riscix1.2
|
os=-riscix1.2
|
||||||
;;
|
;;
|
||||||
|
|
@ -1242,11 +1453,14 @@ case $basic_machine in
|
||||||
arm*-semi)
|
arm*-semi)
|
||||||
os=-aout
|
os=-aout
|
||||||
;;
|
;;
|
||||||
|
c4x-* | tic4x-*)
|
||||||
|
os=-coff
|
||||||
|
;;
|
||||||
# This must come before the *-dec entry.
|
# This must come before the *-dec entry.
|
||||||
pdp10-*)
|
pdp10-*)
|
||||||
os=-tops20
|
os=-tops20
|
||||||
;;
|
;;
|
||||||
pdp11-*)
|
pdp11-*)
|
||||||
os=-none
|
os=-none
|
||||||
;;
|
;;
|
||||||
*-dec | vax-*)
|
*-dec | vax-*)
|
||||||
|
|
@ -1267,6 +1481,9 @@ case $basic_machine in
|
||||||
m68*-cisco)
|
m68*-cisco)
|
||||||
os=-aout
|
os=-aout
|
||||||
;;
|
;;
|
||||||
|
mep-*)
|
||||||
|
os=-elf
|
||||||
|
;;
|
||||||
mips*-cisco)
|
mips*-cisco)
|
||||||
os=-elf
|
os=-elf
|
||||||
;;
|
;;
|
||||||
|
|
@ -1285,9 +1502,15 @@ case $basic_machine in
|
||||||
*-be)
|
*-be)
|
||||||
os=-beos
|
os=-beos
|
||||||
;;
|
;;
|
||||||
|
*-haiku)
|
||||||
|
os=-haiku
|
||||||
|
;;
|
||||||
*-ibm)
|
*-ibm)
|
||||||
os=-aix
|
os=-aix
|
||||||
;;
|
;;
|
||||||
|
*-knuth)
|
||||||
|
os=-mmixware
|
||||||
|
;;
|
||||||
*-wec)
|
*-wec)
|
||||||
os=-proelf
|
os=-proelf
|
||||||
;;
|
;;
|
||||||
|
|
@ -1339,19 +1562,19 @@ case $basic_machine in
|
||||||
*-next)
|
*-next)
|
||||||
os=-nextstep3
|
os=-nextstep3
|
||||||
;;
|
;;
|
||||||
*-gould)
|
*-gould)
|
||||||
os=-sysv
|
os=-sysv
|
||||||
;;
|
;;
|
||||||
*-highlevel)
|
*-highlevel)
|
||||||
os=-bsd
|
os=-bsd
|
||||||
;;
|
;;
|
||||||
*-encore)
|
*-encore)
|
||||||
os=-bsd
|
os=-bsd
|
||||||
;;
|
;;
|
||||||
*-sgi)
|
*-sgi)
|
||||||
os=-irix
|
os=-irix
|
||||||
;;
|
;;
|
||||||
*-siemens)
|
*-siemens)
|
||||||
os=-sysv4
|
os=-sysv4
|
||||||
;;
|
;;
|
||||||
*-masscomp)
|
*-masscomp)
|
||||||
|
|
@ -1420,9 +1643,15 @@ case $basic_machine in
|
||||||
-mvs* | -opened*)
|
-mvs* | -opened*)
|
||||||
vendor=ibm
|
vendor=ibm
|
||||||
;;
|
;;
|
||||||
|
-os400*)
|
||||||
|
vendor=ibm
|
||||||
|
;;
|
||||||
-ptx*)
|
-ptx*)
|
||||||
vendor=sequent
|
vendor=sequent
|
||||||
;;
|
;;
|
||||||
|
-tpf*)
|
||||||
|
vendor=ibm
|
||||||
|
;;
|
||||||
-vxsim* | -vxworks* | -windiss*)
|
-vxsim* | -vxworks* | -windiss*)
|
||||||
vendor=wrs
|
vendor=wrs
|
||||||
;;
|
;;
|
||||||
|
|
@ -1447,7 +1676,7 @@ case $basic_machine in
|
||||||
esac
|
esac
|
||||||
|
|
||||||
echo $basic_machine$os
|
echo $basic_machine$os
|
||||||
exit 0
|
exit
|
||||||
|
|
||||||
# Local variables:
|
# Local variables:
|
||||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||||
|
|
|
||||||
10
configure.in
10
configure.in
|
|
@ -80,11 +80,11 @@ fi
|
||||||
AC_SUBST(HAVE_LIBBZ2)
|
AC_SUBST(HAVE_LIBBZ2)
|
||||||
|
|
||||||
# valgrind checks
|
# valgrind checks
|
||||||
AC_ARG_WITH([valgrind], [AS_HELP_STRING([--with-valgrind],
|
AC_ARG_WITH([valgrind], [AC_HELP_STRING([--with-valgrind],
|
||||||
[Add valgrind hooks])],
|
[Add valgrind hooks])],
|
||||||
[], [check_valgrind=yes])
|
[], [check_valgrind=yes])
|
||||||
|
|
||||||
AS_IF([test "x$check_valgrind" == xyes],
|
AS_IF([test "x$check_valgrind" = xyes],
|
||||||
[AC_MSG_NOTICE([Not using valgrind hooks])],
|
[AC_MSG_NOTICE([Not using valgrind hooks])],
|
||||||
[AC_CHECK_HEADER([valgrind/memcheck.h],
|
[AC_CHECK_HEADER([valgrind/memcheck.h],
|
||||||
[AC_DEFINE([CHECK_WITH_VALGRIND], [1],
|
[AC_DEFINE([CHECK_WITH_VALGRIND], [1],
|
||||||
|
|
@ -181,21 +181,21 @@ AX_C_UNDERSCORES_TRAILING
|
||||||
#######################
|
#######################
|
||||||
|
|
||||||
AC_MSG_CHECKING(for sanity of prefix)
|
AC_MSG_CHECKING(for sanity of prefix)
|
||||||
if test X`echo "$prefix" | wc -w` != X1
|
if test `echo "$prefix" | wc -w` != 1
|
||||||
then
|
then
|
||||||
AC_MSG_ERROR(cannot configure white space in prefix: $prefix)
|
AC_MSG_ERROR(cannot configure white space in prefix: $prefix)
|
||||||
fi
|
fi
|
||||||
AC_MSG_RESULT(ok)
|
AC_MSG_RESULT(ok)
|
||||||
|
|
||||||
AC_MSG_CHECKING(for sanity of exec_prefix)
|
AC_MSG_CHECKING(for sanity of exec_prefix)
|
||||||
if test X`echo "$exec_prefix" | wc -w` != X1
|
if test `echo "$exec_prefix" | wc -w` != 1
|
||||||
then
|
then
|
||||||
AC_MSG_ERROR(cannot configure white space in exec_prefix: $exec_prefix)
|
AC_MSG_ERROR(cannot configure white space in exec_prefix: $exec_prefix)
|
||||||
fi
|
fi
|
||||||
AC_MSG_RESULT(ok)
|
AC_MSG_RESULT(ok)
|
||||||
|
|
||||||
AC_MSG_CHECKING(for sanity of libdir)
|
AC_MSG_CHECKING(for sanity of libdir)
|
||||||
if test X`echo "$libdir" | wc -w` != X1
|
if test `echo "$libdir" | wc -w` != 1
|
||||||
then
|
then
|
||||||
AC_MSG_ERROR(cannot configure white space in libdir: $libdir)
|
AC_MSG_ERROR(cannot configure white space in libdir: $libdir)
|
||||||
fi
|
fi
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1998-2008 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 1998-2009 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -208,8 +208,12 @@ void NetNet::dump_net(ostream&o, unsigned ind) const
|
||||||
o << " scope=" << scope_path(scope());
|
o << " scope=" << scope_path(scope());
|
||||||
o << " #(" << rise_time() << "," << fall_time() << ","
|
o << " #(" << rise_time() << "," << fall_time() << ","
|
||||||
<< decay_time() << ") vector_width=" << vector_width()
|
<< decay_time() << ") vector_width=" << vector_width()
|
||||||
<< " pin_count=" << pin_count()
|
<< " pin_count=" << pin_count();
|
||||||
<< " init=";
|
if (pins_are_virtual()) {
|
||||||
|
o << " pins_are_virtual" << endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
o << " init=";
|
||||||
for (unsigned idx = pin_count() ; idx > 0 ; idx -= 1)
|
for (unsigned idx = pin_count() ; idx > 0 ; idx -= 1)
|
||||||
o << pin(idx-1).get_init();
|
o << pin(idx-1).get_init();
|
||||||
|
|
||||||
|
|
@ -1073,29 +1077,11 @@ void NetRepeat::dump(ostream&o, unsigned ind) const
|
||||||
void NetScope::dump(ostream&o) const
|
void NetScope::dump(ostream&o) const
|
||||||
{
|
{
|
||||||
/* This is a constructed hierarchical name. */
|
/* This is a constructed hierarchical name. */
|
||||||
o << scope_path(this);
|
o << scope_path(this) << " ";
|
||||||
|
|
||||||
switch (type_) {
|
print_type(o);
|
||||||
case BEGIN_END:
|
|
||||||
o << " sequential block";
|
|
||||||
break;
|
|
||||||
case FORK_JOIN:
|
|
||||||
o << " parallel block";
|
|
||||||
break;
|
|
||||||
case FUNC:
|
|
||||||
o << " function";
|
|
||||||
break;
|
|
||||||
case MODULE:
|
|
||||||
o << " module <" << (module_name_? module_name_.str() : "") << ">";
|
|
||||||
break;
|
|
||||||
case TASK:
|
|
||||||
o << " task";
|
|
||||||
break;
|
|
||||||
case GENBLOCK:
|
|
||||||
o << " generate block";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (is_auto()) o << " (automatic)";
|
if (is_auto()) o << " (automatic)";
|
||||||
|
if (is_cell()) o << " (cell)";
|
||||||
o << endl;
|
o << endl;
|
||||||
|
|
||||||
for (unsigned idx = 0 ; idx < attr_cnt() ; idx += 1)
|
for (unsigned idx = 0 ; idx < attr_cnt() ; idx += 1)
|
||||||
|
|
|
||||||
28
dosify.c
28
dosify.c
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2001-2009 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -16,9 +16,6 @@
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
*/
|
*/
|
||||||
#ifdef HAVE_CVS_IDENT
|
|
||||||
#ident "$Id: dosify.c,v 1.5 2003/07/15 16:17:47 steve Exp $"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is a simple program to make a dosified copy of the
|
* This is a simple program to make a dosified copy of the
|
||||||
|
|
@ -51,6 +48,7 @@ int main(int argc, char*argv[])
|
||||||
ofile = fopen(argv[2], "wb");
|
ofile = fopen(argv[2], "wb");
|
||||||
if (ofile == 0) {
|
if (ofile == 0) {
|
||||||
fprintf(stderr, "Unable to open %s for output.\n", argv[2]);
|
fprintf(stderr, "Unable to open %s for output.\n", argv[2]);
|
||||||
|
fclose(ifile);
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -64,25 +62,7 @@ int main(int argc, char*argv[])
|
||||||
pr = ch;
|
pr = ch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fclose(ifile);
|
||||||
|
fclose(ofile);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* $Log: dosify.c,v $
|
|
||||||
* Revision 1.5 2003/07/15 16:17:47 steve
|
|
||||||
* Fix spelling of ifdef.
|
|
||||||
*
|
|
||||||
* Revision 1.4 2003/07/15 03:49:22 steve
|
|
||||||
* Spelling fixes.
|
|
||||||
*
|
|
||||||
* Revision 1.3 2002/08/12 01:34:58 steve
|
|
||||||
* conditional ident string using autoconfig.
|
|
||||||
*
|
|
||||||
* Revision 1.2 2002/08/11 23:47:04 steve
|
|
||||||
* Add missing Log and Ident strings.
|
|
||||||
*
|
|
||||||
* Revision 1.1 2001/08/03 17:06:47 steve
|
|
||||||
* Add install of examples for Windows.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
%{
|
%{
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2001-2009 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -21,9 +21,6 @@
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
*/
|
*/
|
||||||
#ifdef HAVE_CVS_IDENT
|
|
||||||
#ident "$Id: cflexor.lex,v 1.11 2007/03/22 16:08:18 steve Exp $"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
# include "cfparse.h"
|
# include "cfparse.h"
|
||||||
# include "cfparse_misc.h"
|
# include "cfparse_misc.h"
|
||||||
|
|
@ -236,3 +233,17 @@ void cfreset(FILE*fd, const char*path)
|
||||||
current_file = strdup(path);
|
current_file = strdup(path);
|
||||||
cflloc.first_line = 1;
|
cflloc.first_line = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Modern version of flex (>=2.5.9) can clean up the scanner data.
|
||||||
|
*/
|
||||||
|
void destroy_lexor()
|
||||||
|
{
|
||||||
|
# ifdef FLEX_SCANNER
|
||||||
|
# if YY_FLEX_MAJOR_VERSION >= 2 && YY_FLEX_MINOR_VERSION >= 5
|
||||||
|
# if defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9
|
||||||
|
yylex_destroy();
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
%{
|
%{
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 20001 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2001-2009 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -17,10 +17,6 @@
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
*/
|
*/
|
||||||
#ifdef HAVE_CVS_IDENT
|
|
||||||
#ident "$Id: cfparse.y,v 1.12 2007/04/19 02:52:53 steve Exp $"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
# include "globals.h"
|
# include "globals.h"
|
||||||
# include "cfparse_misc.h"
|
# include "cfparse_misc.h"
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef __cfparse_misc_H
|
#ifndef __cfparse_misc_H
|
||||||
#define __cfparse_misc_H
|
#define __cfparse_misc_H
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001 Picture Elements, Inc.
|
* Copyright (c) 2001-2009 Picture Elements, Inc.
|
||||||
* Stephen Williams (steve@picturel.com)
|
* Stephen Williams (steve@picturel.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
|
|
@ -38,6 +38,7 @@ int cflex(void);
|
||||||
int cferror(const char *);
|
int cferror(const char *);
|
||||||
int cfparse(void);
|
int cfparse(void);
|
||||||
void switch_to_command_file(const char *);
|
void switch_to_command_file(const char *);
|
||||||
|
void destroy_lexor();
|
||||||
char *current_file;
|
char *current_file;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,10 @@ iverilog - Icarus Verilog compiler
|
||||||
|
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.B iverilog
|
.B iverilog
|
||||||
[-ESVv] [-Bpath] [-ccmdfile|-fcmdfile] [-Dmacro[=defn]] [-pflag=value]
|
[\-ESVv] [\-Bpath] [\-ccmdfile|\-fcmdfile] [\-Dmacro[=defn]] [\-pflag=value]
|
||||||
[-dname] [-g1995|-g2001|-g2005|-g<feature>]
|
[\-dname] [\-g1995|\-g2001|\-g2005|\-g<feature>]
|
||||||
[-Iincludedir] [-mmodule] [-Mfile] [-Nfile] [-ooutputfilename]
|
[\-Iincludedir] [\-mmodule] [\-Mfile] [\-Nfile] [\-ooutputfilename]
|
||||||
[-stopmodule] [-ttype] [-Tmin/typ/max] [-Wclass] [-ypath] sourcefile
|
[\-stopmodule] [\-ttype] [\-Tmin/typ/max] [\-Wclass] [\-ypath] sourcefile
|
||||||
|
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
.PP
|
.PP
|
||||||
|
|
@ -18,7 +18,6 @@ simulation, and \fIfpga\fP for synthesis. Other target
|
||||||
types are added as code generators are implemented.
|
types are added as code generators are implemented.
|
||||||
|
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
.l
|
|
||||||
\fIiverilog\fP accepts the following options:
|
\fIiverilog\fP accepts the following options:
|
||||||
.TP 8
|
.TP 8
|
||||||
.B -B\fIbase\fP
|
.B -B\fIbase\fP
|
||||||
|
|
@ -55,7 +54,7 @@ is the Verilog input, but with file inclusions and macro references
|
||||||
expanded and removed. This is useful, for example, to preprocess
|
expanded and removed. This is useful, for example, to preprocess
|
||||||
Verilog source for use by other compilers.
|
Verilog source for use by other compilers.
|
||||||
.TP 8
|
.TP 8
|
||||||
.B -g1995\fI|\fP-g2001\fI|\fP-g2005
|
.B -g1995\fI|\fP-g2001\fI|\fP-g2001-noconfig\fI|\fP-g2005
|
||||||
Select the Verilog language \fIgeneration\fP to support in the
|
Select the Verilog language \fIgeneration\fP to support in the
|
||||||
compiler. This selects between \fIIEEE1364-1995\fP,
|
compiler. This selects between \fIIEEE1364-1995\fP,
|
||||||
\fIIEEE1364-2001\fP(2), or \fIIEEE1364-2005\fP. Normally,
|
\fIIEEE1364-2001\fP(2), or \fIIEEE1364-2005\fP. Normally,
|
||||||
|
|
@ -110,9 +109,9 @@ expression changes value, the entire expression is re-evaluated. By
|
||||||
default, parts of the expression that do not depend on the changed
|
default, parts of the expression that do not depend on the changed
|
||||||
input value(s) are not re-evaluated. If an expression contains a call
|
input value(s) are not re-evaluated. If an expression contains a call
|
||||||
to a function that doesn't depend solely on its input values or that
|
to a function that doesn't depend solely on its input values or that
|
||||||
has side effects, the resulting behaviour will differ from that
|
has side effects, the resulting behavior will differ from that
|
||||||
required by the standard. Using \fI-gstrict-ca-eval\fP will force
|
required by the standard. Using \fI-gstrict-ca-eval\fP will force
|
||||||
standard compliant behaviour (with some loss in performance).
|
standard compliant behavior (with some loss in performance).
|
||||||
.TP 8
|
.TP 8
|
||||||
.B -I\fIincludedir\fP
|
.B -I\fIincludedir\fP
|
||||||
Append directory \fIincludedir\fP to list of directories searched
|
Append directory \fIincludedir\fP to list of directories searched
|
||||||
|
|
@ -198,6 +197,11 @@ all the requested classes.
|
||||||
Append the directory to the library module search path. When the
|
Append the directory to the library module search path. When the
|
||||||
compiler finds an undefined module, it looks in these directories for
|
compiler finds an undefined module, it looks in these directories for
|
||||||
files with the right name.
|
files with the right name.
|
||||||
|
.TP 8
|
||||||
|
.B -Y\fIsuffix\fP
|
||||||
|
Add suffix to the list of accepted file name suffixes used when
|
||||||
|
searching a library for cells. The list defaults to the single
|
||||||
|
entry \fI.v\fP.
|
||||||
|
|
||||||
.SH MODULE LIBRARIES
|
.SH MODULE LIBRARIES
|
||||||
|
|
||||||
|
|
@ -250,7 +254,8 @@ after a \fB-Wall\fP argument to suppress isolated warning types.
|
||||||
|
|
||||||
.TP 8
|
.TP 8
|
||||||
.B all
|
.B all
|
||||||
This enables all supported warning categories.
|
This enables the implicit, portbind, select-range, timescale, and
|
||||||
|
sensitivity-entire-array warning categories.
|
||||||
|
|
||||||
.TP 8
|
.TP 8
|
||||||
.B implicit
|
.B implicit
|
||||||
|
|
@ -264,6 +269,12 @@ This enables warnings for ports of module instantiations that are not
|
||||||
connected but probably should be. Dangling input ports, for example,
|
connected but probably should be. Dangling input ports, for example,
|
||||||
will generate a warning.
|
will generate a warning.
|
||||||
|
|
||||||
|
.TP 8
|
||||||
|
.B select-range
|
||||||
|
This enables warnings for constant out of bound selects. This includes
|
||||||
|
partial or fully out of bound selects as well as a select using 'bx as
|
||||||
|
an index.
|
||||||
|
|
||||||
.TP 8
|
.TP 8
|
||||||
.B timescale
|
.B timescale
|
||||||
This enables warnings for inconsistent use of the timescale
|
This enables warnings for inconsistent use of the timescale
|
||||||
|
|
@ -287,6 +298,22 @@ verified. It is expected that many of the warnings will be false
|
||||||
positives, since the code treats the value of all variables and signals
|
positives, since the code treats the value of all variables and signals
|
||||||
as indeterminate.
|
as indeterminate.
|
||||||
|
|
||||||
|
.TP 8
|
||||||
|
.B sensitivity-entire-vector
|
||||||
|
This enables warnings for when a part select within an "always @*"
|
||||||
|
statement results in the entire vector being added to the implicit
|
||||||
|
sensitivity list. Although this behaviour is prescribed by the IEEE
|
||||||
|
standard, it is not what might be expected and can have performance
|
||||||
|
implications if the vector is large.
|
||||||
|
|
||||||
|
.TP 8
|
||||||
|
.B sensitivity-entire-array
|
||||||
|
This enables warnings for when a word select within an "always @*"
|
||||||
|
statement results in the entire array being added to the implicit
|
||||||
|
sensitivity list. Although this behaviour is prescribed by the IEEE
|
||||||
|
standard, it is not what might be expected and can have performance
|
||||||
|
implications if the array is large.
|
||||||
|
|
||||||
.SH "SYSTEM FUNCTION TABLE FILES"
|
.SH "SYSTEM FUNCTION TABLE FILES"
|
||||||
If the source file name as a \fB.sft\fP suffix, then it is taken to be
|
If the source file name as a \fB.sft\fP suffix, then it is taken to be
|
||||||
a system function table file. A System function table file is used to
|
a system function table file. A System function table file is used to
|
||||||
|
|
@ -359,7 +386,7 @@ on to the next library directory.
|
||||||
|
|
||||||
.TP 8
|
.TP 8
|
||||||
.B +libdir+\fIdir\fP
|
.B +libdir+\fIdir\fP
|
||||||
This is another way to specify library directories. See the -y flag.
|
This is another way to specify library directories. See the \-y flag.
|
||||||
|
|
||||||
.TP 8
|
.TP 8
|
||||||
.B +libdir-nocase+\fIdir\fP
|
.B +libdir-nocase+\fIdir\fP
|
||||||
|
|
@ -424,11 +451,11 @@ To compile hello.v to an executable file called a.out:
|
||||||
|
|
||||||
To compile hello.v to an executable file called hello:
|
To compile hello.v to an executable file called hello:
|
||||||
|
|
||||||
iverilog -o hello hello.v
|
iverilog \-o hello hello.v
|
||||||
|
|
||||||
To compile and run explicitly using the vvp runtime:
|
To compile and run explicitly using the vvp runtime:
|
||||||
|
|
||||||
iverilog -ohello.vvp -tvvp hello.v
|
iverilog \-ohello.vvp \-tvvp hello.v
|
||||||
|
|
||||||
.SH "AUTHOR"
|
.SH "AUTHOR"
|
||||||
.nf
|
.nf
|
||||||
|
|
@ -443,7 +470,7 @@ Tips on using, debugging, and developing the compiler can be found at
|
||||||
|
|
||||||
.SH COPYRIGHT
|
.SH COPYRIGHT
|
||||||
.nf
|
.nf
|
||||||
Copyright \(co 2002-2008 Stephen Williams
|
Copyright \(co 2002-2009 Stephen Williams
|
||||||
|
|
||||||
This document can be freely redistributed according to the terms of the
|
This document can be freely redistributed according to the terms of the
|
||||||
GNU General Public License version 2.0
|
GNU General Public License version 2.0
|
||||||
|
|
|
||||||
|
|
@ -281,7 +281,7 @@ static int t_version_only(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
fflush(0);
|
fflush(0);
|
||||||
snprintf(tmp, sizeof tmp, "%s%civl -V -C%s -C%s", pbase, sep,
|
snprintf(tmp, sizeof tmp, "%s%civl -V -C%s -C%s", base, sep,
|
||||||
iconfig_path, iconfig_common_path);
|
iconfig_path, iconfig_common_path);
|
||||||
rc = system(tmp);
|
rc = system(tmp);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
|
|
@ -469,13 +469,18 @@ static void process_warning_switch(const char*name)
|
||||||
if (strcmp(name,"all") == 0) {
|
if (strcmp(name,"all") == 0) {
|
||||||
process_warning_switch("implicit");
|
process_warning_switch("implicit");
|
||||||
process_warning_switch("portbind");
|
process_warning_switch("portbind");
|
||||||
|
process_warning_switch("select-range");
|
||||||
process_warning_switch("timescale");
|
process_warning_switch("timescale");
|
||||||
|
process_warning_switch("sensitivity-entire-array");
|
||||||
} else if (strcmp(name,"implicit") == 0) {
|
} else if (strcmp(name,"implicit") == 0) {
|
||||||
if (! strchr(warning_flags, 'i'))
|
if (! strchr(warning_flags, 'i'))
|
||||||
strcat(warning_flags, "i");
|
strcat(warning_flags, "i");
|
||||||
} else if (strcmp(name,"portbind") == 0) {
|
} else if (strcmp(name,"portbind") == 0) {
|
||||||
if (! strchr(warning_flags, 'p'))
|
if (! strchr(warning_flags, 'p'))
|
||||||
strcat(warning_flags, "p");
|
strcat(warning_flags, "p");
|
||||||
|
} else if (strcmp(name,"select-range") == 0) {
|
||||||
|
if (! strchr(warning_flags, 's'))
|
||||||
|
strcat(warning_flags, "s");
|
||||||
} else if (strcmp(name,"timescale") == 0) {
|
} else if (strcmp(name,"timescale") == 0) {
|
||||||
if (! strchr(warning_flags, 't'))
|
if (! strchr(warning_flags, 't'))
|
||||||
strcat(warning_flags, "t");
|
strcat(warning_flags, "t");
|
||||||
|
|
@ -484,6 +489,12 @@ static void process_warning_switch(const char*name)
|
||||||
} else if (strcmp(name,"infloop") == 0) {
|
} else if (strcmp(name,"infloop") == 0) {
|
||||||
if (! strchr(warning_flags, 'l'))
|
if (! strchr(warning_flags, 'l'))
|
||||||
strcat(warning_flags, "l");
|
strcat(warning_flags, "l");
|
||||||
|
} else if (strcmp(name,"sensitivity-entire-vector") == 0) {
|
||||||
|
if (! strchr(warning_flags, 'v'))
|
||||||
|
strcat(warning_flags, "v");
|
||||||
|
} else if (strcmp(name,"sensitivity-entire-array") == 0) {
|
||||||
|
if (! strchr(warning_flags, 'a'))
|
||||||
|
strcat(warning_flags, "a");
|
||||||
} else if (strcmp(name,"no-implicit") == 0) {
|
} else if (strcmp(name,"no-implicit") == 0) {
|
||||||
char*cp = strchr(warning_flags, 'i');
|
char*cp = strchr(warning_flags, 'i');
|
||||||
if (cp) while (*cp) {
|
if (cp) while (*cp) {
|
||||||
|
|
@ -496,12 +507,30 @@ static void process_warning_switch(const char*name)
|
||||||
cp[0] = cp[1];
|
cp[0] = cp[1];
|
||||||
cp += 1;
|
cp += 1;
|
||||||
}
|
}
|
||||||
|
} else if (strcmp(name,"no-select-range") == 0) {
|
||||||
|
char*cp = strchr(warning_flags, 's');
|
||||||
|
if (cp) while (*cp) {
|
||||||
|
cp[0] = cp[1];
|
||||||
|
cp += 1;
|
||||||
|
}
|
||||||
} else if (strcmp(name,"no-timescale") == 0) {
|
} else if (strcmp(name,"no-timescale") == 0) {
|
||||||
char*cp = strchr(warning_flags, 't');
|
char*cp = strchr(warning_flags, 't');
|
||||||
if (cp) while (*cp) {
|
if (cp) while (*cp) {
|
||||||
cp[0] = cp[1];
|
cp[0] = cp[1];
|
||||||
cp += 1;
|
cp += 1;
|
||||||
}
|
}
|
||||||
|
} else if (strcmp(name,"no-sensitivity-entire-vector") == 0) {
|
||||||
|
char*cp = strchr(warning_flags, 'v');
|
||||||
|
if (cp) while (*cp) {
|
||||||
|
cp[0] = cp[1];
|
||||||
|
cp += 1;
|
||||||
|
}
|
||||||
|
} else if (strcmp(name,"no-sensitivity-entire-array") == 0) {
|
||||||
|
char*cp = strchr(warning_flags, 'a');
|
||||||
|
if (cp) while (*cp) {
|
||||||
|
cp[0] = cp[1];
|
||||||
|
cp += 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -557,6 +586,9 @@ int process_generation(const char*name)
|
||||||
else if (strcmp(name,"2001") == 0)
|
else if (strcmp(name,"2001") == 0)
|
||||||
generation = "2001";
|
generation = "2001";
|
||||||
|
|
||||||
|
else if (strcmp(name,"2001-noconfig") == 0)
|
||||||
|
generation = "2001-noconfig";
|
||||||
|
|
||||||
else if (strcmp(name,"2005") == 0)
|
else if (strcmp(name,"2005") == 0)
|
||||||
generation = "2005";
|
generation = "2005";
|
||||||
|
|
||||||
|
|
@ -866,6 +898,20 @@ int main(int argc, char **argv)
|
||||||
break;
|
break;
|
||||||
case '?':
|
case '?':
|
||||||
default:
|
default:
|
||||||
|
fclose(source_file);
|
||||||
|
remove(source_path);
|
||||||
|
free(source_path);
|
||||||
|
fclose(defines_file);
|
||||||
|
remove(defines_path);
|
||||||
|
free(defines_path);
|
||||||
|
fclose(iconfig_file);
|
||||||
|
remove(iconfig_path);
|
||||||
|
free(iconfig_path);
|
||||||
|
remove(compiled_defines_path);
|
||||||
|
free(compiled_defines_path);
|
||||||
|
while( (command_filename = get_cmd_file()) ) {
|
||||||
|
free(command_filename);
|
||||||
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -937,7 +983,9 @@ int main(int argc, char **argv)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
free(command_filename);
|
free(command_filename);
|
||||||
|
fclose(fp);
|
||||||
}
|
}
|
||||||
|
destroy_lexor();
|
||||||
|
|
||||||
if (depfile) {
|
if (depfile) {
|
||||||
fprintf(defines_file, "M:%s\n", depfile);
|
fprintf(defines_file, "M:%s\n", depfile);
|
||||||
|
|
|
||||||
440
elab_expr.cc
440
elab_expr.cc
|
|
@ -419,10 +419,8 @@ NetExpr* PEBinary::elaborate_expr_base_bits_(Design*des,
|
||||||
// If either of the arguments is unsigned, then process both
|
// If either of the arguments is unsigned, then process both
|
||||||
// of them as unsigned. This only impacts the padding that is
|
// of them as unsigned. This only impacts the padding that is
|
||||||
// done to get the operands to the expr_wid.
|
// done to get the operands to the expr_wid.
|
||||||
if (! lp->has_sign())
|
if (! lp->has_sign()) rp->cast_signed(false);
|
||||||
rp->cast_signed(false);
|
if (! rp->has_sign()) lp->cast_signed(false);
|
||||||
if (! rp->has_sign())
|
|
||||||
lp->cast_signed(false);
|
|
||||||
|
|
||||||
if (expr_wid > 0) {
|
if (expr_wid > 0) {
|
||||||
if (type_is_vectorable(lp->expr_type()))
|
if (type_is_vectorable(lp->expr_type()))
|
||||||
|
|
@ -453,6 +451,12 @@ NetExpr* PEBinary::elaborate_expr_base_div_(Design*des,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If either of the arguments is unsigned, then process both
|
||||||
|
// of them as unsigned. This only impacts the padding that is
|
||||||
|
// done to get the operands to the expr_wid.
|
||||||
|
if (! lp->has_sign()) rp->cast_signed(false);
|
||||||
|
if (! rp->has_sign()) lp->cast_signed(false);
|
||||||
|
|
||||||
/* The original elaboration of the left and right expressions
|
/* The original elaboration of the left and right expressions
|
||||||
already tried to elaborate to the expr_wid. If the
|
already tried to elaborate to the expr_wid. If the
|
||||||
expressions are not that width by now, then they need to be
|
expressions are not that width by now, then they need to be
|
||||||
|
|
@ -643,13 +647,13 @@ NetExpr* PEBinary::elaborate_expr_base_rshift_(Design*des,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NetEConst*rpc = dynamic_cast<NetEConst*> (rp)) {
|
if (NetEConst*rpc = dynamic_cast<NetEConst*> (rp)) {
|
||||||
long shift = rpc->value().as_long();
|
unsigned long shift = rpc->value().as_ulong();
|
||||||
|
|
||||||
// Special case: The shift is the size of the entire
|
// Special case: The shift is the size of the entire
|
||||||
// left operand, and the shift is unsigned. Elaborate as
|
// left operand, and the shift is unsigned. Elaborate as
|
||||||
// a constant-0.
|
// a constant-0.
|
||||||
if ((op_=='r' || (lp->has_sign()==false))
|
if ((op_=='r' || (lp->has_sign()==false)) &&
|
||||||
&& shift >= (long)lp->expr_width()) {
|
shift >= lp->expr_width()) {
|
||||||
|
|
||||||
if (debug_elaborate)
|
if (debug_elaborate)
|
||||||
cerr << get_fileline() << ": debug: "
|
cerr << get_fileline() << ": debug: "
|
||||||
|
|
@ -666,7 +670,11 @@ NetExpr* PEBinary::elaborate_expr_base_rshift_(Design*des,
|
||||||
// Special case: the shift is the size of the entire
|
// Special case: the shift is the size of the entire
|
||||||
// left operand, and the shift is signed. Elaborate as a
|
// left operand, and the shift is signed. Elaborate as a
|
||||||
// replication of the top bit of the left expression.
|
// replication of the top bit of the left expression.
|
||||||
if (shift >= (long)lp->expr_width()) {
|
//
|
||||||
|
// The above test assures us that op_ == 'R' && the left
|
||||||
|
// argument is signed when the shift is greater than the
|
||||||
|
// expression width.
|
||||||
|
if (shift >= lp->expr_width()) {
|
||||||
|
|
||||||
if (debug_elaborate)
|
if (debug_elaborate)
|
||||||
cerr << get_fileline() << ": debug: "
|
cerr << get_fileline() << ": debug: "
|
||||||
|
|
@ -685,34 +693,10 @@ NetExpr* PEBinary::elaborate_expr_base_rshift_(Design*des,
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Special case: shift is negative (so do a left shift)
|
|
||||||
// and is greater then the output width. Replace the
|
|
||||||
// expression with a constant-0.
|
|
||||||
if (shift < 0 && (0-shift) >= use_wid) {
|
|
||||||
if (debug_elaborate)
|
|
||||||
cerr << get_fileline() << ": debug: "
|
|
||||||
<< "Value signed-right-shifted " << shift
|
|
||||||
<< " beyond width of " << use_wid
|
|
||||||
<< "." << endl;
|
|
||||||
|
|
||||||
tmp = make_const_0(use_wid);
|
|
||||||
tmp->set_line(*this);
|
|
||||||
return tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
ivl_assert(*this, shift >= 0);
|
|
||||||
|
|
||||||
if (debug_elaborate)
|
|
||||||
cerr << get_fileline() << ": debug: "
|
|
||||||
<< "Value signed-right-shifted " << shift
|
|
||||||
<< " beyond width of " << lp->expr_width()
|
|
||||||
<< ". shift=" << shift
|
|
||||||
<< ", expr_wid=" << expr_wid
|
|
||||||
<< ", expr=" << *lp << endl;
|
|
||||||
|
|
||||||
// If this is lossless, then pad the left expression
|
// If this is lossless, then pad the left expression
|
||||||
// enough to cover the right shift.
|
// enough to cover the right shift.
|
||||||
if (expr_wid == -2 && use_wid+shift > (long)lp->expr_width()) {
|
if (expr_wid == -2 && use_wid+shift > lp->expr_width()) {
|
||||||
|
lp->cast_signed(lp->has_sign() && op_=='R');
|
||||||
lp = pad_to_width(lp, use_wid + shift, *this);
|
lp = pad_to_width(lp, use_wid + shift, *this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1504,6 +1488,12 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
|
||||||
def->port(idx)->data_type(),
|
def->port(idx)->data_type(),
|
||||||
def->port(idx)->vector_width(),
|
def->port(idx)->vector_width(),
|
||||||
tmp);
|
tmp);
|
||||||
|
if (NetEEvent*evt = dynamic_cast<NetEEvent*> (parms[idx])) {
|
||||||
|
cerr << evt->get_fileline() << ": error: An event '"
|
||||||
|
<< evt->event()->name() << "' can not be a user "
|
||||||
|
"function argument." << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
}
|
||||||
if (debug_elaborate)
|
if (debug_elaborate)
|
||||||
cerr << get_fileline() << ": debug:"
|
cerr << get_fileline() << ": debug:"
|
||||||
<< " function " << path_
|
<< " function " << path_
|
||||||
|
|
@ -1633,7 +1623,7 @@ NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tmp->expr_type() == IVL_VT_REAL) {
|
if (tmp->expr_type() == IVL_VT_REAL) {
|
||||||
cerr << tmp->get_fileline() << ": error: concatenation "
|
cerr << tmp->get_fileline() << ": error: Concatenation "
|
||||||
<< "repeat expression can not be REAL." << endl;
|
<< "repeat expression can not be REAL." << endl;
|
||||||
des->errors += 1;
|
des->errors += 1;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -1643,7 +1633,7 @@ NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope,
|
||||||
|
|
||||||
if (rep == 0) {
|
if (rep == 0) {
|
||||||
cerr << get_fileline() << ": error: "
|
cerr << get_fileline() << ": error: "
|
||||||
"concatenation repeat expression cannot be evaluated."
|
"Concatenation repeat expression cannot be evaluated."
|
||||||
<< endl;
|
<< endl;
|
||||||
cerr << get_fileline() << ": : The expression is: "
|
cerr << get_fileline() << ": : The expression is: "
|
||||||
<< *tmp << endl;
|
<< *tmp << endl;
|
||||||
|
|
@ -1702,18 +1692,20 @@ NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope,
|
||||||
|
|
||||||
ex->set_line(*parms_[idx]);
|
ex->set_line(*parms_[idx]);
|
||||||
|
|
||||||
if (! ex->has_width()) {
|
|
||||||
cerr << ex->get_fileline() << ": error: "
|
|
||||||
<< "concatenation operand has indefinite width: "
|
|
||||||
<< *ex << endl;
|
|
||||||
des->errors += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ex->expr_type() == IVL_VT_REAL) {
|
if (ex->expr_type() == IVL_VT_REAL) {
|
||||||
cerr << ex->get_fileline() << ": error: "
|
cerr << ex->get_fileline() << ": error: "
|
||||||
<< "concatenation operand can not be REAL: "
|
<< "Concatenation operand can not be real: "
|
||||||
<< *ex << endl;
|
<< *parms_[idx] << endl;
|
||||||
des->errors += 1;
|
des->errors += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! ex->has_width()) {
|
||||||
|
cerr << ex->get_fileline() << ": error: "
|
||||||
|
<< "Concatenation operand \"" << *parms_[idx]
|
||||||
|
<< "\" has indefinite width." << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
wid_sum += ex->expr_width();
|
wid_sum += ex->expr_width();
|
||||||
|
|
@ -1727,6 +1719,7 @@ NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope,
|
||||||
<< "have zero width in this context." << endl;
|
<< "have zero width in this context." << endl;
|
||||||
des->errors += 1;
|
des->errors += 1;
|
||||||
concat_depth -= 1;
|
concat_depth -= 1;
|
||||||
|
delete tmp;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1790,7 +1783,9 @@ bool PEIdent::calculate_parts_(Design*des, NetScope*scope,
|
||||||
two bit select expressions, and both must be
|
two bit select expressions, and both must be
|
||||||
constant. Evaluate them and pass the results back to
|
constant. Evaluate them and pass the results back to
|
||||||
the caller. */
|
the caller. */
|
||||||
|
need_constant_expr = true;
|
||||||
NetExpr*lsb_ex = elab_and_eval(des, scope, index_tail.lsb, lsb_wid);
|
NetExpr*lsb_ex = elab_and_eval(des, scope, index_tail.lsb, lsb_wid);
|
||||||
|
need_constant_expr = false;
|
||||||
NetEConst*lsb_c = dynamic_cast<NetEConst*>(lsb_ex);
|
NetEConst*lsb_c = dynamic_cast<NetEConst*>(lsb_ex);
|
||||||
if (lsb_c == 0) {
|
if (lsb_c == 0) {
|
||||||
cerr << index_tail.lsb->get_fileline() << ": error: "
|
cerr << index_tail.lsb->get_fileline() << ": error: "
|
||||||
|
|
@ -1808,7 +1803,9 @@ bool PEIdent::calculate_parts_(Design*des, NetScope*scope,
|
||||||
lsb = lsb_c->value().as_long();
|
lsb = lsb_c->value().as_long();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
need_constant_expr = true;
|
||||||
NetExpr*msb_ex = elab_and_eval(des, scope, index_tail.msb, msb_wid);
|
NetExpr*msb_ex = elab_and_eval(des, scope, index_tail.msb, msb_wid);
|
||||||
|
need_constant_expr = false;
|
||||||
NetEConst*msb_c = dynamic_cast<NetEConst*>(msb_ex);
|
NetEConst*msb_c = dynamic_cast<NetEConst*>(msb_ex);
|
||||||
if (msb_c == 0) {
|
if (msb_c == 0) {
|
||||||
cerr << index_tail.msb->get_fileline() << ": error: "
|
cerr << index_tail.msb->get_fileline() << ": error: "
|
||||||
|
|
@ -1845,7 +1842,9 @@ bool PEIdent::calculate_up_do_width_(Design*des, NetScope*scope,
|
||||||
/* Calculate the width expression (in the lsb_ position)
|
/* Calculate the width expression (in the lsb_ position)
|
||||||
first. If the expression is not constant, error but guess 1
|
first. If the expression is not constant, error but guess 1
|
||||||
so we can keep going and find more errors. */
|
so we can keep going and find more errors. */
|
||||||
|
need_constant_expr = true;
|
||||||
NetExpr*wid_ex = elab_and_eval(des, scope, index_tail.lsb, -1);
|
NetExpr*wid_ex = elab_and_eval(des, scope, index_tail.lsb, -1);
|
||||||
|
need_constant_expr = false;
|
||||||
NetEConst*wid_c = dynamic_cast<NetEConst*>(wid_ex);
|
NetEConst*wid_c = dynamic_cast<NetEConst*>(wid_ex);
|
||||||
|
|
||||||
if (wid_c == 0) {
|
if (wid_c == 0) {
|
||||||
|
|
@ -1943,7 +1942,10 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope,
|
||||||
if (!name_tail.index.empty()) {
|
if (!name_tail.index.empty()) {
|
||||||
probe_index_expr_width(des, scope, name_tail);
|
probe_index_expr_width(des, scope, name_tail);
|
||||||
const index_component_t&index_tail = name_tail.index.back();
|
const index_component_t&index_tail = name_tail.index.back();
|
||||||
use_sel = index_tail.sel;
|
// Skip full array word net selects.
|
||||||
|
if (!net || (name_tail.index.size() > net->array_dimensions())) {
|
||||||
|
use_sel = index_tail.sel;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned use_width = UINT_MAX;
|
unsigned use_width = UINT_MAX;
|
||||||
|
|
@ -2214,12 +2216,12 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
||||||
}
|
}
|
||||||
|
|
||||||
static verinum param_part_select_bits(const verinum&par_val, long wid,
|
static verinum param_part_select_bits(const verinum&par_val, long wid,
|
||||||
long lsv, long par_lsv)
|
long lsv)
|
||||||
{
|
{
|
||||||
verinum result (verinum::Vx, wid, true);
|
verinum result (verinum::Vx, wid, true);
|
||||||
|
|
||||||
for (long idx = 0 ; idx < wid ; idx += 1) {
|
for (long idx = 0 ; idx < wid ; idx += 1) {
|
||||||
long off = idx + lsv - par_lsv;
|
long off = idx + lsv;
|
||||||
if (off < 0)
|
if (off < 0)
|
||||||
result.set(idx, verinum::Vx);
|
result.set(idx, verinum::Vx);
|
||||||
else if (off < (long)par_val.len())
|
else if (off < (long)par_val.len())
|
||||||
|
|
@ -2234,7 +2236,7 @@ static verinum param_part_select_bits(const verinum&par_val, long wid,
|
||||||
|
|
||||||
// If the input is a string, and the part select is working on
|
// If the input is a string, and the part select is working on
|
||||||
// byte boundaries, then make the result into a string.
|
// byte boundaries, then make the result into a string.
|
||||||
if (par_val.is_string() && (labs(lsv-par_lsv)%8 == 0) && (wid%8 == 0))
|
if (par_val.is_string() && (labs(lsv)%8 == 0) && (wid%8 == 0))
|
||||||
return result.as_string();
|
return result.as_string();
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
@ -2259,7 +2261,7 @@ NetExpr* PEIdent::elaborate_expr_param_part_(Design*des, NetScope*scope,
|
||||||
|
|
||||||
if (! parts_defined_flag) {
|
if (! parts_defined_flag) {
|
||||||
if (debug_elaborate)
|
if (debug_elaborate)
|
||||||
cerr << get_fileline() << ": debug: Part select of paramter "
|
cerr << get_fileline() << ": debug: Part select of parameter "
|
||||||
<< "has x/z bits, so resorting to 'bx result." << endl;
|
<< "has x/z bits, so resorting to 'bx result." << endl;
|
||||||
|
|
||||||
long wid = 1 + labs(par_msv-par_lsv);
|
long wid = 1 + labs(par_msv-par_lsv);
|
||||||
|
|
@ -2290,28 +2292,56 @@ NetExpr* PEIdent::elaborate_expr_param_part_(Design*des, NetScope*scope,
|
||||||
const NetEConst*par_ex = dynamic_cast<const NetEConst*> (par);
|
const NetEConst*par_ex = dynamic_cast<const NetEConst*> (par);
|
||||||
ivl_assert(*this, par_ex);
|
ivl_assert(*this, par_ex);
|
||||||
|
|
||||||
verinum result = param_part_select_bits(par_ex->value(), wid, lsv, par_lsv);
|
verinum result = param_part_select_bits(par_ex->value(), wid, lsv-par_lsv);
|
||||||
NetEConst*result_ex = new NetEConst(result);
|
NetEConst*result_ex = new NetEConst(result);
|
||||||
result_ex->set_line(*this);
|
result_ex->set_line(*this);
|
||||||
|
|
||||||
return result_ex;
|
return result_ex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void warn_param_ob(long par_msv, long par_lsv, bool defined,
|
||||||
|
long par_base, unsigned long wid, long pwid,
|
||||||
|
const LineInfo *info, perm_string name, bool up)
|
||||||
|
{
|
||||||
|
long par_max;
|
||||||
|
|
||||||
|
if (defined) {
|
||||||
|
if (par_msv < par_lsv) par_max = par_lsv-par_msv;
|
||||||
|
else par_max = par_msv-par_lsv;
|
||||||
|
} else {
|
||||||
|
if (pwid < 0) par_max = integer_width;
|
||||||
|
else par_max = pwid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Is this a select before the start of the parameter? */
|
||||||
|
if (par_base < 0) {
|
||||||
|
cerr << info->get_fileline() << ": warning: " << name << "["
|
||||||
|
<< par_base;
|
||||||
|
if (up) cerr << "+:";
|
||||||
|
else cerr << "-:";
|
||||||
|
cerr << wid << "] is selecting before vector." << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Is this a select after the end of the parameter? */
|
||||||
|
if (par_base + (long)wid - 1 > par_max) {
|
||||||
|
cerr << info->get_fileline() << ": warning: " << name << "["
|
||||||
|
<< par_base << "+:" << wid << "] is selecting after vector."
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
NetExpr* PEIdent::elaborate_expr_param_idx_up_(Design*des, NetScope*scope,
|
NetExpr* PEIdent::elaborate_expr_param_idx_up_(Design*des, NetScope*scope,
|
||||||
const NetExpr*par,
|
const NetExpr*par,
|
||||||
NetScope*found_in,
|
NetScope*found_in,
|
||||||
const NetExpr*par_msb,
|
const NetExpr*par_msb,
|
||||||
const NetExpr*par_lsb) const
|
const NetExpr*par_lsb) const
|
||||||
{
|
{
|
||||||
|
|
||||||
long par_msv, par_lsv;
|
long par_msv, par_lsv;
|
||||||
bool flag = calculate_param_range_(des, scope, par_msb, par_msv, par_lsb, par_lsv);
|
if(! calculate_param_range_(des, scope, par_msb, par_msv,
|
||||||
if (!flag)
|
par_lsb, par_lsv)) return 0;
|
||||||
return 0;
|
|
||||||
|
|
||||||
NetExpr*base = calculate_up_do_base_(des, scope);
|
NetExpr*base = calculate_up_do_base_(des, scope);
|
||||||
if (base == 0)
|
if (base == 0) return 0;
|
||||||
return 0;
|
|
||||||
|
|
||||||
unsigned long wid = 0;
|
unsigned long wid = 0;
|
||||||
calculate_up_do_width_(des, scope, wid);
|
calculate_up_do_width_(des, scope, wid);
|
||||||
|
|
@ -2327,22 +2357,139 @@ NetExpr* PEIdent::elaborate_expr_param_idx_up_(Design*des, NetScope*scope,
|
||||||
// Handle the special case that the base is constant. In this
|
// Handle the special case that the base is constant. In this
|
||||||
// case, just precalculate the entire constant result.
|
// case, just precalculate the entire constant result.
|
||||||
if (NetEConst*base_c = dynamic_cast<NetEConst*> (base)) {
|
if (NetEConst*base_c = dynamic_cast<NetEConst*> (base)) {
|
||||||
|
if (! base_c->value().is_defined()) {
|
||||||
|
NetEConst *ex;
|
||||||
|
ex = new NetEConst(verinum(verinum::Vx, wid, true));
|
||||||
|
ex->set_line(*this);
|
||||||
|
if (warn_ob_select) {
|
||||||
|
perm_string name = peek_tail_name(path_);
|
||||||
|
cerr << get_fileline() << ": warning: " << name
|
||||||
|
<< "['bx+:" << wid
|
||||||
|
<< "] is always outside vector." << endl;
|
||||||
|
}
|
||||||
|
return ex;
|
||||||
|
}
|
||||||
long lsv = base_c->value().as_long();
|
long lsv = base_c->value().as_long();
|
||||||
|
long par_base = par_lsv;
|
||||||
|
|
||||||
// Watch out for reversed bit numbering. We're making
|
// Watch out for reversed bit numbering. We're making
|
||||||
// the part select from LSB to MSB.
|
// the part select from LSB to MSB.
|
||||||
if (par_msv < par_lsv)
|
if (par_msv < par_lsv) {
|
||||||
lsv = lsv - wid + 1;
|
par_base = lsv;
|
||||||
|
lsv = par_lsv - wid + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (warn_ob_select) {
|
||||||
|
bool defined = true;
|
||||||
|
// Check to see if the parameter has a defined range.
|
||||||
|
if (par_msb == 0) {
|
||||||
|
assert(par_lsb == 0);
|
||||||
|
defined = false;
|
||||||
|
}
|
||||||
|
// Get the parameter values width.
|
||||||
|
long pwid = -1;
|
||||||
|
if (par_ex->has_width()) pwid = par_ex->expr_width()-1;
|
||||||
|
perm_string name = peek_tail_name(path_);
|
||||||
|
warn_param_ob(par_msv, par_lsv, defined, lsv-par_base, wid,
|
||||||
|
pwid, this, name, true);
|
||||||
|
}
|
||||||
verinum result = param_part_select_bits(par_ex->value(), wid,
|
verinum result = param_part_select_bits(par_ex->value(), wid,
|
||||||
lsv, par_lsv);
|
lsv-par_base);
|
||||||
NetEConst*result_ex = new NetEConst(result);
|
NetEConst*result_ex = new NetEConst(result);
|
||||||
result_ex->set_line(*this);
|
result_ex->set_line(*this);
|
||||||
return result_ex;
|
return result_ex;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((par_msv < par_lsv) && (wid>1))
|
if (par_msv >= par_lsv) {
|
||||||
base = make_add_expr(base, 1-(long)wid);
|
if (par_lsv != 0) base = make_add_expr(base, -par_lsv);
|
||||||
|
} else {
|
||||||
|
base = make_sub_expr(par_lsv-wid+1, base);
|
||||||
|
}
|
||||||
|
|
||||||
|
NetExpr*tmp = par->dup_expr();
|
||||||
|
tmp = new NetESelect(tmp, base, wid);
|
||||||
|
tmp->set_line(*this);
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
NetExpr* PEIdent::elaborate_expr_param_idx_do_(Design*des, NetScope*scope,
|
||||||
|
const NetExpr*par,
|
||||||
|
NetScope*found_in,
|
||||||
|
const NetExpr*par_msb,
|
||||||
|
const NetExpr*par_lsb) const
|
||||||
|
{
|
||||||
|
long par_msv, par_lsv;
|
||||||
|
if(! calculate_param_range_(des, scope, par_msb, par_msv,
|
||||||
|
par_lsb, par_lsv)) return 0;
|
||||||
|
|
||||||
|
NetExpr*base = calculate_up_do_base_(des, scope);
|
||||||
|
if (base == 0) return 0;
|
||||||
|
|
||||||
|
unsigned long wid = 0;
|
||||||
|
calculate_up_do_width_(des, scope, wid);
|
||||||
|
|
||||||
|
const NetEConst*par_ex = dynamic_cast<const NetEConst*> (par);
|
||||||
|
ivl_assert(*this, par_ex);
|
||||||
|
|
||||||
|
if (debug_elaborate)
|
||||||
|
cerr << get_fileline() << ": debug: Calculate part select "
|
||||||
|
<< "[" << *base << "-:" << wid << "] from range "
|
||||||
|
<< "[" << par_msv << ":" << par_lsv << "]." << endl;
|
||||||
|
|
||||||
|
// Handle the special case that the base is constant. In this
|
||||||
|
// case, just precalculate the entire constant result.
|
||||||
|
if (NetEConst*base_c = dynamic_cast<NetEConst*> (base)) {
|
||||||
|
if (! base_c->value().is_defined()) {
|
||||||
|
NetEConst *ex;
|
||||||
|
ex = new NetEConst(verinum(verinum::Vx, wid, true));
|
||||||
|
ex->set_line(*this);
|
||||||
|
if (warn_ob_select) {
|
||||||
|
perm_string name = peek_tail_name(path_);
|
||||||
|
cerr << get_fileline() << ": warning: " << name
|
||||||
|
<< "['bx-:" << wid
|
||||||
|
<< "] is always outside vector." << endl;
|
||||||
|
}
|
||||||
|
return ex;
|
||||||
|
}
|
||||||
|
long lsv = base_c->value().as_long();
|
||||||
|
long par_base = par_lsv + wid - 1;
|
||||||
|
|
||||||
|
// Watch out for reversed bit numbering. We're making
|
||||||
|
// the part select from LSB to MSB.
|
||||||
|
if (par_msv < par_lsv) {
|
||||||
|
par_base = lsv;
|
||||||
|
lsv = par_lsv;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (warn_ob_select) {
|
||||||
|
bool defined = true;
|
||||||
|
// Check to see if the parameter has a defined range.
|
||||||
|
if (par_msb == 0) {
|
||||||
|
assert(par_lsb == 0);
|
||||||
|
defined = false;
|
||||||
|
}
|
||||||
|
// Get the parameter values width.
|
||||||
|
long pwid = -1;
|
||||||
|
if (par_ex->has_width()) pwid = par_ex->expr_width()-1;
|
||||||
|
perm_string name = peek_tail_name(path_);
|
||||||
|
warn_param_ob(par_msv, par_lsv, defined, lsv-par_base, wid,
|
||||||
|
pwid, this, name, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
verinum result = param_part_select_bits(par_ex->value(), wid,
|
||||||
|
lsv-par_base);
|
||||||
|
NetEConst*result_ex = new NetEConst(result);
|
||||||
|
result_ex->set_line(*this);
|
||||||
|
return result_ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (par_msv >= par_lsv) {
|
||||||
|
if (long offset = par_lsv+wid-1) {
|
||||||
|
base = make_add_expr(base, -offset);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
base = make_sub_expr(par_lsv, base);
|
||||||
|
}
|
||||||
|
|
||||||
NetExpr*tmp = par->dup_expr();
|
NetExpr*tmp = par->dup_expr();
|
||||||
tmp = new NetESelect(tmp, base, wid);
|
tmp = new NetESelect(tmp, base, wid);
|
||||||
|
|
@ -2368,6 +2515,15 @@ NetExpr* PEIdent::elaborate_expr_param_(Design*des,
|
||||||
if (!name_tail.index.empty())
|
if (!name_tail.index.empty())
|
||||||
use_sel = name_tail.index.back().sel;
|
use_sel = name_tail.index.back().sel;
|
||||||
|
|
||||||
|
if (par->expr_type() == IVL_VT_REAL &&
|
||||||
|
use_sel != index_component_t::SEL_NONE) {
|
||||||
|
perm_string name = peek_tail_name(path_);
|
||||||
|
cerr << get_fileline() << ": error: "
|
||||||
|
<< "can not select part of real parameter: " << name << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// NOTE TO SELF: This is the way I want to see this code
|
// NOTE TO SELF: This is the way I want to see this code
|
||||||
// structured. This closely follows the structure of the
|
// structured. This closely follows the structure of the
|
||||||
// elaborate_expr_net_ code, which splits all the various
|
// elaborate_expr_net_ code, which splits all the various
|
||||||
|
|
@ -2380,47 +2536,16 @@ NetExpr* PEIdent::elaborate_expr_param_(Design*des,
|
||||||
return elaborate_expr_param_idx_up_(des, scope, par, found_in,
|
return elaborate_expr_param_idx_up_(des, scope, par, found_in,
|
||||||
par_msb, par_lsb);
|
par_msb, par_lsb);
|
||||||
|
|
||||||
|
if (use_sel == index_component_t::SEL_IDX_DO)
|
||||||
|
return elaborate_expr_param_idx_do_(des, scope, par, found_in,
|
||||||
|
par_msb, par_lsb);
|
||||||
|
|
||||||
// NOTE TO SELF (continued): The code below should be
|
// NOTE TO SELF (continued): The code below should be
|
||||||
// rewritten in the above format, as I get to it.
|
// rewritten in the above format, as I get to it.
|
||||||
|
|
||||||
NetExpr*tmp = par->dup_expr();
|
NetExpr*tmp = par->dup_expr();
|
||||||
|
|
||||||
if (use_sel == index_component_t::SEL_IDX_DO) {
|
if (use_sel == index_component_t::SEL_BIT) {
|
||||||
|
|
||||||
ivl_assert(*this, !name_tail.index.empty());
|
|
||||||
const index_component_t&index_tail = name_tail.index.back();
|
|
||||||
ivl_assert(*this, index_tail.msb);
|
|
||||||
ivl_assert(*this, index_tail.lsb);
|
|
||||||
|
|
||||||
/* Get and evaluate the width of the index
|
|
||||||
select. This must be constant. */
|
|
||||||
NetExpr*wid_ex = elab_and_eval(des, scope, index_tail.lsb, -1);
|
|
||||||
NetEConst*wid_ec = dynamic_cast<NetEConst*> (wid_ex);
|
|
||||||
if (wid_ec == 0) {
|
|
||||||
cerr << index_tail.lsb->get_fileline() << ": error: "
|
|
||||||
<< "Second expression of indexed part select "
|
|
||||||
<< "most be constant." << endl;
|
|
||||||
des->errors += 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned wid = wid_ec->value().as_ulong();
|
|
||||||
|
|
||||||
NetExpr*idx_ex = elab_and_eval(des, scope, index_tail.msb, -1);
|
|
||||||
if (idx_ex == 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (use_sel == index_component_t::SEL_IDX_DO && wid > 1) {
|
|
||||||
idx_ex = make_add_expr(idx_ex, 1-(long)wid);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Wrap the param expression with a part select. */
|
|
||||||
tmp = new NetESelect(tmp, idx_ex, wid);
|
|
||||||
|
|
||||||
|
|
||||||
} else if (use_sel == index_component_t::SEL_BIT) {
|
|
||||||
ivl_assert(*this, !name_tail.index.empty());
|
ivl_assert(*this, !name_tail.index.empty());
|
||||||
const index_component_t&index_tail = name_tail.index.back();
|
const index_component_t&index_tail = name_tail.index.back();
|
||||||
ivl_assert(*this, index_tail.msb);
|
ivl_assert(*this, index_tail.msb);
|
||||||
|
|
@ -2603,6 +2728,9 @@ NetExpr* PEIdent::elaborate_expr_net_word_(Design*des, NetScope*scope,
|
||||||
// Special case: The index is out of range, so the value
|
// Special case: The index is out of range, so the value
|
||||||
// of this expression is a 'bx vector the width of a word.
|
// of this expression is a 'bx vector the width of a word.
|
||||||
if (!net->array_index_is_valid(addr)) {
|
if (!net->array_index_is_valid(addr)) {
|
||||||
|
cerr << get_fileline() << ": warning: returning 'bx for out "
|
||||||
|
"of bounds array access " << net->name()
|
||||||
|
<< "[" << addr << "]." << endl;
|
||||||
NetEConst*resx = make_const_x(net->vector_width());
|
NetEConst*resx = make_const_x(net->vector_width());
|
||||||
resx->set_line(*this);
|
resx->set_line(*this);
|
||||||
delete word_index;
|
delete word_index;
|
||||||
|
|
@ -2638,6 +2766,18 @@ NetExpr* PEIdent::elaborate_expr_net_word_(Design*des, NetScope*scope,
|
||||||
if (name_tail.index.size() > 1)
|
if (name_tail.index.size() > 1)
|
||||||
word_sel = name_tail.index.back().sel;
|
word_sel = name_tail.index.back().sel;
|
||||||
|
|
||||||
|
if (net->get_scalar() &&
|
||||||
|
word_sel != index_component_t::SEL_NONE) {
|
||||||
|
cerr << get_fileline() << ": error: can not select part of ";
|
||||||
|
if (res->expr_type() == IVL_VT_REAL) cerr << "real";
|
||||||
|
else cerr << "scalar";
|
||||||
|
cerr << " array word: " << net->name()
|
||||||
|
<<"[" << *word_index << "]" << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
delete res;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (word_sel == index_component_t::SEL_PART)
|
if (word_sel == index_component_t::SEL_PART)
|
||||||
return elaborate_expr_net_part_(des, scope, res, found_in);
|
return elaborate_expr_net_part_(des, scope, res, found_in);
|
||||||
|
|
||||||
|
|
@ -2651,6 +2791,7 @@ NetExpr* PEIdent::elaborate_expr_net_word_(Design*des, NetScope*scope,
|
||||||
return elaborate_expr_net_bit_(des, scope, res, found_in);
|
return elaborate_expr_net_bit_(des, scope, res, found_in);
|
||||||
|
|
||||||
ivl_assert(*this, word_sel == index_component_t::SEL_NONE);
|
ivl_assert(*this, word_sel == index_component_t::SEL_NONE);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2745,15 +2886,47 @@ NetExpr* PEIdent::elaborate_expr_net_idx_up_(Design*des, NetScope*scope,
|
||||||
if (net->sig()->sb_to_idx(lsv) == 0 &&
|
if (net->sig()->sb_to_idx(lsv) == 0 &&
|
||||||
wid == net->vector_width()) {
|
wid == net->vector_width()) {
|
||||||
delete base;
|
delete base;
|
||||||
|
net->cast_signed(false);
|
||||||
return net;
|
return net;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
long offset = 0;
|
||||||
|
if (net->msi() < net->lsi()) {
|
||||||
|
offset = -wid + 1;
|
||||||
|
}
|
||||||
// Otherwise, make a part select that covers the right
|
// Otherwise, make a part select that covers the right
|
||||||
// range.
|
// range.
|
||||||
ex = new NetEConst(verinum(net->sig()->sb_to_idx(lsv)));
|
ex = new NetEConst(verinum(net->sig()->sb_to_idx(lsv) +
|
||||||
|
offset));
|
||||||
|
if (warn_ob_select) {
|
||||||
|
long rel_base = net->sig()->sb_to_idx(lsv) + offset;
|
||||||
|
if (rel_base < 0) {
|
||||||
|
cerr << get_fileline() << ": warning: "
|
||||||
|
<< net->name();
|
||||||
|
if (net->word_index()) cerr << "[]";
|
||||||
|
cerr << "[" << lsv << "+:" << wid
|
||||||
|
<< "] is selecting before vector." << endl;
|
||||||
|
}
|
||||||
|
if (rel_base + wid > net->vector_width()) {
|
||||||
|
cerr << get_fileline() << ": warning: "
|
||||||
|
<< net->name();
|
||||||
|
if (net->word_index()) cerr << "[]";
|
||||||
|
cerr << "[" << lsv << "+:" << wid
|
||||||
|
<< "] is selecting after vector." << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Return 'bx for an undefined base.
|
// Return 'bx for an undefined base.
|
||||||
ex = new NetEConst(verinum(verinum::Vx, 1, false));
|
ex = new NetEConst(verinum(verinum::Vx, wid, true));
|
||||||
|
ex->set_line(*this);
|
||||||
|
delete base;
|
||||||
|
if (warn_ob_select) {
|
||||||
|
cerr << get_fileline() << ": warning: " << net->name();
|
||||||
|
if (net->word_index()) cerr << "[]";
|
||||||
|
cerr << "['bx+:" << wid
|
||||||
|
<< "] is always outside vector." << endl;
|
||||||
|
}
|
||||||
|
return ex;
|
||||||
}
|
}
|
||||||
NetESelect*ss = new NetESelect(net, ex, wid);
|
NetESelect*ss = new NetESelect(net, ex, wid);
|
||||||
ss->set_line(*this);
|
ss->set_line(*this);
|
||||||
|
|
@ -2764,11 +2937,9 @@ NetExpr* PEIdent::elaborate_expr_net_idx_up_(Design*des, NetScope*scope,
|
||||||
|
|
||||||
if (net->msi() > net->lsi()) {
|
if (net->msi() > net->lsi()) {
|
||||||
if (long offset = net->lsi())
|
if (long offset = net->lsi())
|
||||||
base = make_add_expr(base, 0-offset);
|
base = make_add_expr(base, -offset);
|
||||||
} else {
|
} else {
|
||||||
long vwid = net->lsi() - net->msi() + 1;
|
base = make_sub_expr(net->lsi()-wid+1, base);
|
||||||
long offset = net->msi();
|
|
||||||
base = make_sub_expr(vwid-offset-wid, base);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NetESelect*ss = new NetESelect(net, base, wid);
|
NetESelect*ss = new NetESelect(net, base, wid);
|
||||||
|
|
@ -2807,15 +2978,47 @@ NetExpr* PEIdent::elaborate_expr_net_idx_do_(Design*des, NetScope*scope,
|
||||||
if (net->sig()->sb_to_idx(lsv) == (signed) (wid-1) &&
|
if (net->sig()->sb_to_idx(lsv) == (signed) (wid-1) &&
|
||||||
wid == net->vector_width()) {
|
wid == net->vector_width()) {
|
||||||
delete base;
|
delete base;
|
||||||
|
net->cast_signed(false);
|
||||||
return net;
|
return net;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
long offset = 0;
|
||||||
|
if (net->msi() > net->lsi()) {
|
||||||
|
offset = -wid + 1;
|
||||||
|
}
|
||||||
// Otherwise, make a part select that covers the right
|
// Otherwise, make a part select that covers the right
|
||||||
// range.
|
// range.
|
||||||
ex = new NetEConst(verinum(net->sig()->sb_to_idx(lsv)-wid+1));
|
ex = new NetEConst(verinum(net->sig()->sb_to_idx(lsv) +
|
||||||
|
offset));
|
||||||
|
if (warn_ob_select) {
|
||||||
|
long rel_base = net->sig()->sb_to_idx(lsv) + offset;
|
||||||
|
if (rel_base < 0) {
|
||||||
|
cerr << get_fileline() << ": warning: "
|
||||||
|
<< net->name();
|
||||||
|
if (net->word_index()) cerr << "[]";
|
||||||
|
cerr << "[" << lsv << "+:" << wid
|
||||||
|
<< "] is selecting before vector." << endl;
|
||||||
|
}
|
||||||
|
if (rel_base + wid > net->vector_width()) {
|
||||||
|
cerr << get_fileline() << ": warning: "
|
||||||
|
<< net->name();
|
||||||
|
if (net->word_index()) cerr << "[]";
|
||||||
|
cerr << "[" << lsv << "-:" << wid
|
||||||
|
<< "] is selecting after vector." << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Return 'bx for an undefined base.
|
// Return 'bx for an undefined base.
|
||||||
ex = new NetEConst(verinum(verinum::Vx, 1, false));
|
ex = new NetEConst(verinum(verinum::Vx, wid, true));
|
||||||
|
ex->set_line(*this);
|
||||||
|
delete base;
|
||||||
|
if (warn_ob_select) {
|
||||||
|
cerr << get_fileline() << ": warning: " << net->name();
|
||||||
|
if (net->word_index()) cerr << "[]";
|
||||||
|
cerr << "['bx-:" << wid
|
||||||
|
<< "] is always outside vector." << endl;
|
||||||
|
}
|
||||||
|
return ex;
|
||||||
}
|
}
|
||||||
NetESelect*ss = new NetESelect(net, ex, wid);
|
NetESelect*ss = new NetESelect(net, ex, wid);
|
||||||
ss->set_line(*this);
|
ss->set_line(*this);
|
||||||
|
|
@ -2824,16 +3027,19 @@ NetExpr* PEIdent::elaborate_expr_net_idx_do_(Design*des, NetScope*scope,
|
||||||
return ss;
|
return ss;
|
||||||
}
|
}
|
||||||
|
|
||||||
long offset = net->lsi();
|
if (net->msi() > net->lsi()) {
|
||||||
NetExpr*base_adjusted = wid > 1
|
if (long offset = net->lsi()+wid-1)
|
||||||
? make_add_expr(base,1-(long)wid-offset)
|
base = make_add_expr(base, -offset);
|
||||||
: (offset == 0? base : make_add_expr(base, 0-offset));
|
} else {
|
||||||
NetESelect*ss = new NetESelect(net, base_adjusted, wid);
|
base = make_sub_expr(net->lsi(), base);
|
||||||
|
}
|
||||||
|
|
||||||
|
NetESelect*ss = new NetESelect(net, base, wid);
|
||||||
ss->set_line(*this);
|
ss->set_line(*this);
|
||||||
|
|
||||||
if (debug_elaborate) {
|
if (debug_elaborate) {
|
||||||
cerr << get_fileline() << ": debug: Elaborate part "
|
cerr << get_fileline() << ": debug: Elaborate part "
|
||||||
<< "select base="<< *base_adjusted << ", wid="<< wid << endl;
|
<< "select base="<< *base << ", wid="<< wid << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ss;
|
return ss;
|
||||||
|
|
@ -2932,6 +3138,16 @@ NetExpr* PEIdent::elaborate_expr_net(Design*des, NetScope*scope,
|
||||||
if (! path_.back().index.empty())
|
if (! path_.back().index.empty())
|
||||||
use_sel = path_.back().index.back().sel;
|
use_sel = path_.back().index.back().sel;
|
||||||
|
|
||||||
|
if (net->get_scalar() &&
|
||||||
|
use_sel != index_component_t::SEL_NONE) {
|
||||||
|
cerr << get_fileline() << ": error: can not select part of ";
|
||||||
|
if (node->expr_type() == IVL_VT_REAL) cerr << "real: ";
|
||||||
|
else cerr << "scalar: ";
|
||||||
|
cerr << net->name() << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// If this is a part select of a signal, then make a new
|
// If this is a part select of a signal, then make a new
|
||||||
// temporary signal that is connected to just the
|
// temporary signal that is connected to just the
|
||||||
// selected bits. The lsb_ and msb_ expressions are from
|
// selected bits. The lsb_ and msb_ expressions are from
|
||||||
|
|
|
||||||
146
elab_lval.cc
146
elab_lval.cc
|
|
@ -118,17 +118,20 @@ NetAssign_* PEConcat::elaborate_lval(Design*des,
|
||||||
|
|
||||||
NetAssign_*tmp = parms_[idx]->elaborate_lval(des, scope, is_force);
|
NetAssign_*tmp = parms_[idx]->elaborate_lval(des, scope, is_force);
|
||||||
|
|
||||||
|
if (tmp->expr_type() == IVL_VT_REAL) {
|
||||||
|
cerr << parms_[idx]->get_fileline() << ": error: "
|
||||||
|
<< "concatenation operand can not be real: "
|
||||||
|
<< *parms_[idx] << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/* If the l-value doesn't elaborate, the error was
|
/* If the l-value doesn't elaborate, the error was
|
||||||
already detected and printed. We just skip it and let
|
already detected and printed. We just skip it and let
|
||||||
the compiler catch more errors. */
|
the compiler catch more errors. */
|
||||||
if (tmp == 0)
|
if (tmp == 0) continue;
|
||||||
continue;
|
|
||||||
|
|
||||||
assert(tmp);
|
|
||||||
|
|
||||||
|
|
||||||
/* Link the new l-value to the previous one. */
|
/* Link the new l-value to the previous one. */
|
||||||
|
|
||||||
NetAssign_*last = tmp;
|
NetAssign_*last = tmp;
|
||||||
while (last->more)
|
while (last->more)
|
||||||
last = last->more;
|
last = last->more;
|
||||||
|
|
@ -195,6 +198,17 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
||||||
if (reg->array_dimensions() > 0)
|
if (reg->array_dimensions() > 0)
|
||||||
return elaborate_lval_net_word_(des, scope, reg);
|
return elaborate_lval_net_word_(des, scope, reg);
|
||||||
|
|
||||||
|
// This must be after the array word elaboration above!
|
||||||
|
if (reg->get_scalar() &&
|
||||||
|
use_sel != index_component_t::SEL_NONE) {
|
||||||
|
cerr << get_fileline() << ": error: can not select part of ";
|
||||||
|
if (reg->data_type() == IVL_VT_REAL) cerr << "real: ";
|
||||||
|
else cerr << "scalar: ";
|
||||||
|
cerr << reg->name() << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (use_sel == index_component_t::SEL_PART) {
|
if (use_sel == index_component_t::SEL_PART) {
|
||||||
NetAssign_*lv = new NetAssign_(reg);
|
NetAssign_*lv = new NetAssign_(reg);
|
||||||
elaborate_lval_net_part_(des, scope, lv);
|
elaborate_lval_net_part_(des, scope, lv);
|
||||||
|
|
@ -243,13 +257,11 @@ NetAssign_* PEIdent::elaborate_lval_net_word_(Design*des,
|
||||||
ivl_assert(*this, index_head.msb != 0);
|
ivl_assert(*this, index_head.msb != 0);
|
||||||
ivl_assert(*this, index_head.lsb == 0);
|
ivl_assert(*this, index_head.lsb == 0);
|
||||||
|
|
||||||
|
// These are not used, but they need to have a default value.
|
||||||
ivl_variable_type_t expr_type_tmp = IVL_VT_NO_TYPE;
|
ivl_variable_type_t expr_type_tmp = IVL_VT_NO_TYPE;
|
||||||
// This not used, but it needs to have a default value.
|
|
||||||
bool unsized_flag_tmp = false;
|
bool unsized_flag_tmp = false;
|
||||||
index_head.msb->test_width(des, scope,
|
index_head.msb->test_width(des, scope, integer_width, integer_width,
|
||||||
reg->vector_width(), reg->vector_width(),
|
expr_type_tmp, unsized_flag_tmp);
|
||||||
expr_type_tmp,
|
|
||||||
unsized_flag_tmp);
|
|
||||||
|
|
||||||
NetExpr*word = elab_and_eval(des, scope, index_head.msb, -1);
|
NetExpr*word = elab_and_eval(des, scope, index_head.msb, -1);
|
||||||
|
|
||||||
|
|
@ -289,6 +301,20 @@ NetAssign_* PEIdent::elaborate_lval_net_word_(Design*des,
|
||||||
if (name_tail.index.size() > 1)
|
if (name_tail.index.size() > 1)
|
||||||
use_sel = name_tail.index.back().sel;
|
use_sel = name_tail.index.back().sel;
|
||||||
|
|
||||||
|
if (reg->get_scalar() &&
|
||||||
|
use_sel != index_component_t::SEL_NONE) {
|
||||||
|
cerr << get_fileline() << ": error: can not select part of ";
|
||||||
|
if (reg->data_type() == IVL_VT_REAL) cerr << "real";
|
||||||
|
else cerr << "scalar";
|
||||||
|
cerr << " array word: " << reg->name()
|
||||||
|
<< "[" << *word << "]" << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (use_sel == index_component_t::SEL_BIT)
|
||||||
|
elaborate_lval_net_bit_(des, scope, lv);
|
||||||
|
|
||||||
if (use_sel == index_component_t::SEL_PART)
|
if (use_sel == index_component_t::SEL_PART)
|
||||||
elaborate_lval_net_part_(des, scope, lv);
|
elaborate_lval_net_part_(des, scope, lv);
|
||||||
|
|
||||||
|
|
@ -310,16 +336,14 @@ bool PEIdent::elaborate_lval_net_bit_(Design*des,
|
||||||
|
|
||||||
NetNet*reg = lv->sig();
|
NetNet*reg = lv->sig();
|
||||||
|
|
||||||
|
// These are not used, but they need to have a default value.
|
||||||
ivl_variable_type_t expr_type_tmp = IVL_VT_NO_TYPE;
|
ivl_variable_type_t expr_type_tmp = IVL_VT_NO_TYPE;
|
||||||
// This not used, but it needs to have a default value.
|
|
||||||
bool unsized_flag_tmp = false;
|
bool unsized_flag_tmp = false;
|
||||||
index_tail.msb->test_width(des, scope,
|
index_tail.msb->test_width(des, scope, integer_width, integer_width,
|
||||||
lv->lwidth(), lv->lwidth(),
|
expr_type_tmp, unsized_flag_tmp);
|
||||||
expr_type_tmp,
|
|
||||||
unsized_flag_tmp);
|
|
||||||
|
|
||||||
|
|
||||||
// Bit selects have a single select expression. Evaluate the
|
// Bit selects have a single select expression. Evaluate the
|
||||||
// constant value and treat it as a part select with a bit
|
// constant value and treat it as a part select with a bit
|
||||||
// width of 1.
|
// width of 1.
|
||||||
NetExpr*mux = elab_and_eval(des, scope, index_tail.msb, -1);
|
NetExpr*mux = elab_and_eval(des, scope, index_tail.msb, -1);
|
||||||
|
|
@ -444,24 +468,86 @@ bool PEIdent::elaborate_lval_net_idx_(Design*des,
|
||||||
unsigned long wid;
|
unsigned long wid;
|
||||||
calculate_up_do_width_(des, scope, wid);
|
calculate_up_do_width_(des, scope, wid);
|
||||||
|
|
||||||
|
// These are not used, but they need to have a default value.
|
||||||
ivl_variable_type_t expr_type_tmp = IVL_VT_NO_TYPE;
|
ivl_variable_type_t expr_type_tmp = IVL_VT_NO_TYPE;
|
||||||
// This not used, but it needs to have a default value.
|
|
||||||
bool unsized_flag_tmp = false;
|
bool unsized_flag_tmp = false;
|
||||||
index_tail.msb->test_width(des, scope,
|
index_tail.msb->test_width(des, scope, integer_width, integer_width,
|
||||||
wid, wid,
|
expr_type_tmp, unsized_flag_tmp);
|
||||||
expr_type_tmp,
|
|
||||||
unsized_flag_tmp);
|
|
||||||
|
|
||||||
NetExpr*base = elab_and_eval(des, scope, index_tail.msb, -1);
|
NetExpr*base = elab_and_eval(des, scope, index_tail.msb, -1);
|
||||||
|
|
||||||
/* Correct the mux for the range of the vector. */
|
// Handle the special case that the base is constant. For this
|
||||||
if (reg->msb() < reg->lsb())
|
// case we can reduce the expression.
|
||||||
base = make_sub_expr(reg->lsb(), base);
|
if (NetEConst*base_c = dynamic_cast<NetEConst*> (base)) {
|
||||||
else if (reg->lsb() != 0)
|
// For the undefined case just let the constant pass and
|
||||||
base = make_add_expr(base, - reg->lsb());
|
// we will handle it in the code generator.
|
||||||
|
if (base_c->value().is_defined()) {
|
||||||
if (use_sel == index_component_t::SEL_IDX_DO && wid > 1 ) {
|
long lsv = base_c->value().as_long();
|
||||||
base = make_add_expr(base, 1-(long)wid);
|
long offset = 0;
|
||||||
|
if (((reg->msb() < reg->lsb()) &&
|
||||||
|
use_sel == index_component_t::SEL_IDX_UP) ||
|
||||||
|
((reg->msb() > reg->lsb()) &&
|
||||||
|
use_sel == index_component_t::SEL_IDX_DO)) {
|
||||||
|
offset = -wid + 1;
|
||||||
|
}
|
||||||
|
delete base;
|
||||||
|
base = new NetEConst(verinum(reg->sb_to_idx(lsv) + offset));
|
||||||
|
if (warn_ob_select) {
|
||||||
|
long rel_base = reg->sb_to_idx(lsv) + offset;
|
||||||
|
if (rel_base < 0) {
|
||||||
|
cerr << get_fileline() << ": warning: " << reg->name();
|
||||||
|
if (reg->array_dimensions() > 0) cerr << "[]";
|
||||||
|
cerr << "[" << lsv;
|
||||||
|
if (use_sel == index_component_t::SEL_IDX_UP) {
|
||||||
|
cerr << "+:";
|
||||||
|
} else {
|
||||||
|
cerr << "-:";
|
||||||
|
}
|
||||||
|
cerr << wid << "] is selecting before vector." << endl;
|
||||||
|
}
|
||||||
|
if (rel_base + wid > reg->vector_width()) {
|
||||||
|
cerr << get_fileline() << ": warning: " << reg->name();
|
||||||
|
if (reg->array_dimensions() > 0) cerr << "[]";
|
||||||
|
cerr << "[" << lsv;
|
||||||
|
if (use_sel == index_component_t::SEL_IDX_UP) {
|
||||||
|
cerr << "+:";
|
||||||
|
} else {
|
||||||
|
cerr << "-:";
|
||||||
|
}
|
||||||
|
cerr << wid << "] is selecting after vector." << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (warn_ob_select) {
|
||||||
|
cerr << get_fileline() << ": warning: " << reg->name();
|
||||||
|
if (reg->array_dimensions() > 0) cerr << "[]";
|
||||||
|
cerr << "['bx";
|
||||||
|
if (use_sel == index_component_t::SEL_IDX_UP) {
|
||||||
|
cerr << "+:";
|
||||||
|
} else {
|
||||||
|
cerr << "-:";
|
||||||
|
}
|
||||||
|
cerr << wid << "] is always outside vector." << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Correct the mux for the range of the vector. */
|
||||||
|
if (use_sel == index_component_t::SEL_IDX_UP) {
|
||||||
|
if (reg->msb() > reg->lsb()) {
|
||||||
|
if (long offset = reg->lsb())
|
||||||
|
base = make_add_expr(base, -offset);
|
||||||
|
} else {
|
||||||
|
base = make_sub_expr(reg->lsb()-wid+1, base);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// This is assumed to be a SEL_IDX_DO.
|
||||||
|
if (reg->msb() > reg->lsb()) {
|
||||||
|
if (long offset = reg->lsb()+wid-1)
|
||||||
|
base = make_add_expr(base, -offset);
|
||||||
|
} else {
|
||||||
|
base = make_sub_expr(reg->lsb(), base);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (debug_elaborate)
|
if (debug_elaborate)
|
||||||
|
|
|
||||||
100
elab_net.cc
100
elab_net.cc
|
|
@ -72,10 +72,16 @@ NetNet* PEConcat::elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||||
} else {
|
} else {
|
||||||
nets[idx] = parms_[idx]->elaborate_lnet(des, scope);
|
nets[idx] = parms_[idx]->elaborate_lnet(des, scope);
|
||||||
}
|
}
|
||||||
if (nets[idx] == 0)
|
|
||||||
|
if (nets[idx] == 0) errors += 1;
|
||||||
|
else if (nets[idx]->data_type() == IVL_VT_REAL) {
|
||||||
|
cerr << parms_[idx]->get_fileline() << ": error: "
|
||||||
|
<< "concatenation operand can no be real: "
|
||||||
|
<< *parms_[idx] << endl;
|
||||||
errors += 1;
|
errors += 1;
|
||||||
else
|
continue;
|
||||||
width += nets[idx]->vector_width();
|
} else width += nets[idx]->vector_width();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If any of the sub expressions failed to elaborate, then
|
/* If any of the sub expressions failed to elaborate, then
|
||||||
|
|
@ -173,7 +179,7 @@ NetNet* PEIdent::make_implicit_net_(Design*des, NetScope*scope) const
|
||||||
assert(nettype != NetNet::NONE);
|
assert(nettype != NetNet::NONE);
|
||||||
|
|
||||||
NetNet*sig = new NetNet(scope, peek_tail_name(path_),
|
NetNet*sig = new NetNet(scope, peek_tail_name(path_),
|
||||||
NetNet::IMPLICIT, 1);
|
nettype, 1);
|
||||||
sig->set_line(*this);
|
sig->set_line(*this);
|
||||||
/* Implicit nets are always scalar logic. */
|
/* Implicit nets are always scalar logic. */
|
||||||
sig->data_type(IVL_VT_LOGIC);
|
sig->data_type(IVL_VT_LOGIC);
|
||||||
|
|
@ -220,7 +226,9 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
|
||||||
|
|
||||||
case index_component_t::SEL_IDX_DO:
|
case index_component_t::SEL_IDX_DO:
|
||||||
case index_component_t::SEL_IDX_UP: {
|
case index_component_t::SEL_IDX_UP: {
|
||||||
|
need_constant_expr = true;
|
||||||
NetExpr*tmp_ex = elab_and_eval(des, scope, index_tail.msb, -1);
|
NetExpr*tmp_ex = elab_and_eval(des, scope, index_tail.msb, -1);
|
||||||
|
need_constant_expr = false;
|
||||||
NetEConst*tmp = dynamic_cast<NetEConst*>(tmp_ex);
|
NetEConst*tmp = dynamic_cast<NetEConst*>(tmp_ex);
|
||||||
if (!tmp) {
|
if (!tmp) {
|
||||||
cerr << get_fileline() << ": error: indexed part select of "
|
cerr << get_fileline() << ": error: indexed part select of "
|
||||||
|
|
@ -230,15 +238,33 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
long midx_val = tmp->value().as_long();
|
|
||||||
midx = sig->sb_to_idx(midx_val);
|
|
||||||
delete tmp_ex;
|
|
||||||
|
|
||||||
/* The width (a constant) is calculated here. */
|
/* The width (a constant) is calculated here. */
|
||||||
unsigned long wid = 0;
|
unsigned long wid = 0;
|
||||||
bool flag = calculate_up_do_width_(des, scope, wid);
|
bool flag = calculate_up_do_width_(des, scope, wid);
|
||||||
if (! flag)
|
if (! flag) return false;
|
||||||
|
|
||||||
|
/* We have an undefined index and that is out of range. */
|
||||||
|
if (! tmp->value().is_defined()) {
|
||||||
|
if (warn_ob_select) {
|
||||||
|
cerr << get_fileline() << ": warning: "
|
||||||
|
<< sig->name();
|
||||||
|
if (sig->array_dimensions() > 0) cerr << "[]";
|
||||||
|
cerr << "['bx";
|
||||||
|
if (index_tail.sel ==
|
||||||
|
index_component_t::SEL_IDX_UP) {
|
||||||
|
cerr << "+:";
|
||||||
|
} else {
|
||||||
|
cerr << "-:";
|
||||||
|
}
|
||||||
|
cerr << wid << "] is always outside vector."
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
long midx_val = tmp->value().as_long();
|
||||||
|
midx = sig->sb_to_idx(midx_val);
|
||||||
|
delete tmp_ex;
|
||||||
|
|
||||||
if (index_tail.sel == index_component_t::SEL_IDX_UP)
|
if (index_tail.sel == index_component_t::SEL_IDX_UP)
|
||||||
lidx = sig->sb_to_idx(midx_val+wid-1);
|
lidx = sig->sb_to_idx(midx_val+wid-1);
|
||||||
|
|
@ -252,9 +278,19 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Warn about an indexed part select that is out of range. */
|
/* Warn about an indexed part select that is out of range. */
|
||||||
if (midx >= (long)sig->vector_width() || lidx < 0) {
|
if (warn_ob_select && (lidx < 0)) {
|
||||||
cerr << get_fileline() << ": warning: Indexed part "
|
cerr << get_fileline() << ": warning: " << sig->name();
|
||||||
"select " << sig->name();
|
if (sig->array_dimensions() > 0) cerr << "[]";
|
||||||
|
cerr << "[" << midx_val;
|
||||||
|
if (index_tail.sel == index_component_t::SEL_IDX_UP) {
|
||||||
|
cerr << "+:";
|
||||||
|
} else {
|
||||||
|
cerr << "-:";
|
||||||
|
}
|
||||||
|
cerr << wid << "] is selecting before vector." << endl;
|
||||||
|
}
|
||||||
|
if (warn_ob_select && (midx >= (long)sig->vector_width())) {
|
||||||
|
cerr << get_fileline() << ": warning: " << sig->name();
|
||||||
if (sig->array_dimensions() > 0) {
|
if (sig->array_dimensions() > 0) {
|
||||||
cerr << "[]";
|
cerr << "[]";
|
||||||
}
|
}
|
||||||
|
|
@ -264,7 +300,7 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
|
||||||
} else {
|
} else {
|
||||||
cerr << "-:";
|
cerr << "-:";
|
||||||
}
|
}
|
||||||
cerr << wid << "] is out of range." << endl;
|
cerr << wid << "] is selecting after vector." << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This is completely out side the signal so just skip it. */
|
/* This is completely out side the signal so just skip it. */
|
||||||
|
|
@ -415,7 +451,7 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||||
// Default part select is the entire word.
|
// Default part select is the entire word.
|
||||||
unsigned midx = sig->vector_width()-1, lidx = 0;
|
unsigned midx = sig->vector_width()-1, lidx = 0;
|
||||||
// The default word select is the first.
|
// The default word select is the first.
|
||||||
unsigned widx = 0;
|
long widx = 0;
|
||||||
|
|
||||||
const name_component_t&name_tail = path_.back();
|
const name_component_t&name_tail = path_.back();
|
||||||
|
|
||||||
|
|
@ -437,7 +473,15 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||||
}
|
}
|
||||||
ivl_assert(*this, index_head.sel == index_component_t::SEL_BIT);
|
ivl_assert(*this, index_head.sel == index_component_t::SEL_BIT);
|
||||||
|
|
||||||
|
// These are not used, but they need to have a default value.
|
||||||
|
ivl_variable_type_t expr_type_tmp = IVL_VT_NO_TYPE;
|
||||||
|
bool unsized_flag_tmp = false;
|
||||||
|
index_head.msb->test_width(des, scope,
|
||||||
|
integer_width, integer_width,
|
||||||
|
expr_type_tmp, unsized_flag_tmp);
|
||||||
|
need_constant_expr = true;
|
||||||
NetExpr*tmp_ex = elab_and_eval(des, scope, index_head.msb, -1);
|
NetExpr*tmp_ex = elab_and_eval(des, scope, index_head.msb, -1);
|
||||||
|
need_constant_expr = false;
|
||||||
NetEConst*tmp = dynamic_cast<NetEConst*>(tmp_ex);
|
NetEConst*tmp = dynamic_cast<NetEConst*>(tmp_ex);
|
||||||
if (!tmp) {
|
if (!tmp) {
|
||||||
cerr << get_fileline() << ": error: array " << sig->name()
|
cerr << get_fileline() << ": error: array " << sig->name()
|
||||||
|
|
@ -456,6 +500,17 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||||
|
|
||||||
/* The array has a part/bit select at the end. */
|
/* The array has a part/bit select at the end. */
|
||||||
if (name_tail.index.size() > sig->array_dimensions()) {
|
if (name_tail.index.size() > sig->array_dimensions()) {
|
||||||
|
if (sig->get_scalar()) {
|
||||||
|
cerr << get_fileline() << ": error: "
|
||||||
|
<< "can not select part of ";
|
||||||
|
if (sig->data_type() == IVL_VT_REAL) cerr << "real";
|
||||||
|
else cerr << "scalar";
|
||||||
|
cerr << " array word: " << sig->name()
|
||||||
|
<< "[" << widx_val << "]" << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
long midx_tmp, lidx_tmp;
|
long midx_tmp, lidx_tmp;
|
||||||
if (! eval_part_select_(des, scope, sig, midx_tmp, lidx_tmp))
|
if (! eval_part_select_(des, scope, sig, midx_tmp, lidx_tmp))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -471,6 +526,16 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||||
lidx = lidx_tmp;
|
lidx = lidx_tmp;
|
||||||
}
|
}
|
||||||
} else if (!name_tail.index.empty()) {
|
} else if (!name_tail.index.empty()) {
|
||||||
|
if (sig->get_scalar()) {
|
||||||
|
cerr << get_fileline() << ": error: "
|
||||||
|
<< "can not select part of ";
|
||||||
|
if (sig->data_type() == IVL_VT_REAL) cerr << "real: ";
|
||||||
|
else cerr << "scalar: ";
|
||||||
|
cerr << sig->name() << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
long midx_tmp, lidx_tmp;
|
long midx_tmp, lidx_tmp;
|
||||||
if (! eval_part_select_(des, scope, sig, midx_tmp, lidx_tmp))
|
if (! eval_part_select_(des, scope, sig, midx_tmp, lidx_tmp))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -489,7 +554,12 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||||
unsigned subnet_wid = midx-lidx+1;
|
unsigned subnet_wid = midx-lidx+1;
|
||||||
|
|
||||||
if (sig->pin_count() > 1) {
|
if (sig->pin_count() > 1) {
|
||||||
assert(widx < sig->pin_count());
|
if (widx < 0 || widx >= (long) sig->pin_count()) {
|
||||||
|
cerr << get_fileline() << ": warning: ignoring out of "
|
||||||
|
"bounds l-value array access "
|
||||||
|
<< sig->name() << "[" << widx << "]." << endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
|
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
|
||||||
sig->type(), sig->vector_width());
|
sig->type(), sig->vector_width());
|
||||||
|
|
|
||||||
|
|
@ -150,11 +150,19 @@ NetEConcat* PEConcat::elaborate_pexpr(Design*des, NetScope*scope) const
|
||||||
/* Elaborate all the operands and attach them to the concat
|
/* Elaborate all the operands and attach them to the concat
|
||||||
node. Use the elaborate_pexpr method instead of the
|
node. Use the elaborate_pexpr method instead of the
|
||||||
elaborate_expr method. */
|
elaborate_expr method. */
|
||||||
|
bool fail = false;
|
||||||
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
|
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
|
||||||
assert(parms_[idx]);
|
assert(parms_[idx]);
|
||||||
NetExpr*ex = parms_[idx]->elaborate_pexpr(des, scope);
|
NetExpr*ex = parms_[idx]->elaborate_pexpr(des, scope);
|
||||||
if (ex == 0) continue;
|
if (ex == 0) continue;
|
||||||
|
|
||||||
|
if (ex->expr_type() == IVL_VT_REAL) {
|
||||||
|
cerr << ex->get_fileline() << ": error: concatenation "
|
||||||
|
<< "operand can not be real: " << *ex << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
fail = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
ex->set_line(*parms_[idx]);
|
ex->set_line(*parms_[idx]);
|
||||||
|
|
||||||
if (dynamic_cast<NetEParam*>(ex)) {
|
if (dynamic_cast<NetEParam*>(ex)) {
|
||||||
|
|
@ -167,13 +175,18 @@ NetEConcat* PEConcat::elaborate_pexpr(Design*des, NetScope*scope) const
|
||||||
<< "concatenation has indefinite width: "
|
<< "concatenation has indefinite width: "
|
||||||
<< *ex << endl;
|
<< *ex << endl;
|
||||||
des->errors += 1;
|
des->errors += 1;
|
||||||
delete tmp;
|
fail = true;
|
||||||
return 0;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
tmp->set(idx, ex);
|
tmp->set(idx, ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fail) {
|
||||||
|
delete tmp;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -194,6 +207,14 @@ NetExpr*PEIdent::elaborate_pexpr(Design*des, NetScope*scope) const
|
||||||
name_component_t name_tail = path_.back();
|
name_component_t name_tail = path_.back();
|
||||||
oldpath.pop_back();
|
oldpath.pop_back();
|
||||||
|
|
||||||
|
if (path_.size() > 1) {
|
||||||
|
cerr << get_fileline() << ": error: parameter r-value expression "
|
||||||
|
"does not support hierarchical references `" << path_
|
||||||
|
<< "`." << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
NetScope*pscope = scope;
|
NetScope*pscope = scope;
|
||||||
if (path_.size() > 0) {
|
if (path_.size() > 0) {
|
||||||
list<hname_t> tmp = eval_scope_path(des, scope, oldpath);
|
list<hname_t> tmp = eval_scope_path(des, scope, oldpath);
|
||||||
|
|
@ -216,8 +237,9 @@ NetExpr*PEIdent::elaborate_pexpr(Design*des, NetScope*scope) const
|
||||||
ivl_assert(*this, pscope);
|
ivl_assert(*this, pscope);
|
||||||
}
|
}
|
||||||
if (ex == 0) {
|
if (ex == 0) {
|
||||||
cerr << get_fileline() << ": error: identifier ``" << name_tail.name <<
|
cerr << get_fileline() << ": error: identifier `"
|
||||||
"'' is not a parameter in "<< scope_path(scope)<< "." << endl;
|
<< name_tail.name << "` is not a parameter in "
|
||||||
|
<< scope_path(scope)<< "." << endl;
|
||||||
des->errors += 1;
|
des->errors += 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
447
elab_scope.cc
447
elab_scope.cc
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000-2008 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2000-2009 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -174,6 +174,15 @@ static void elaborate_scope_parameters_(Design*des, NetScope*scope,
|
||||||
for (mparm_it_t cur = parameters.begin()
|
for (mparm_it_t cur = parameters.begin()
|
||||||
; cur != parameters.end() ; cur ++) {
|
; cur != parameters.end() ; cur ++) {
|
||||||
|
|
||||||
|
// A parameter can not have the same name as a genvar.
|
||||||
|
if (scope->find_genvar((*cur).first)) {
|
||||||
|
cerr << cur->second.get_fileline()
|
||||||
|
<< ": error: parameter and genvar in '"
|
||||||
|
<< scope->fullname() << "' have the same name '"
|
||||||
|
<< (*cur).first << "'." << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
}
|
||||||
|
|
||||||
elaborate_parm_item_((*cur).first, (*cur).second, des, scope);
|
elaborate_parm_item_((*cur).first, (*cur).second, des, scope);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -184,6 +193,15 @@ static void elaborate_scope_localparams_(Design*des, NetScope*scope,
|
||||||
for (mparm_it_t cur = localparams.begin()
|
for (mparm_it_t cur = localparams.begin()
|
||||||
; cur != localparams.end() ; cur ++) {
|
; cur != localparams.end() ; cur ++) {
|
||||||
|
|
||||||
|
// A localparam can not have the same name as a genvar.
|
||||||
|
if (scope->find_genvar((*cur).first)) {
|
||||||
|
cerr << cur->second.get_fileline()
|
||||||
|
<< ": error: localparam and genvar in '"
|
||||||
|
<< scope->fullname() << "' have the same name '"
|
||||||
|
<< (*cur).first << "'." << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
}
|
||||||
|
|
||||||
elaborate_parm_item_((*cur).first, (*cur).second, des, scope);
|
elaborate_parm_item_((*cur).first, (*cur).second, des, scope);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -238,13 +256,38 @@ static void elaborate_scope_tasks(Design*des, NetScope*scope,
|
||||||
; cur != tasks.end() ; cur ++ ) {
|
; cur != tasks.end() ; cur ++ ) {
|
||||||
|
|
||||||
hname_t use_name( (*cur).first );
|
hname_t use_name( (*cur).first );
|
||||||
if (scope->child(use_name)) {
|
// A task can not have the same name as another scope object.
|
||||||
cerr << loc.get_fileline() << ": error: task/scope name "
|
const NetScope *child = scope->child(use_name);
|
||||||
<< use_name << " already used in this context."
|
if (child) {
|
||||||
<< endl;
|
cerr << cur->second->get_fileline() << ": error: task and ";
|
||||||
|
child->print_type(cerr);
|
||||||
|
cerr << " in '" << scope->fullname()
|
||||||
|
<< "' have the same name '" << use_name << "'." << endl;
|
||||||
des->errors += 1;
|
des->errors += 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A task can not have the same name as a genvar.
|
||||||
|
if (scope->find_genvar((*cur).first)) {
|
||||||
|
cerr << cur->second->get_fileline()
|
||||||
|
<< ": error: task and genvar in '"
|
||||||
|
<< scope->fullname() << "' have the same name '"
|
||||||
|
<< (*cur).first << "'." << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A task can not have the same name as a parameter.
|
||||||
|
const NetExpr *ex_msb, *ex_lsb;
|
||||||
|
const NetExpr *parm = scope->get_parameter((*cur).first, ex_msb,
|
||||||
|
ex_lsb);
|
||||||
|
if (parm) {
|
||||||
|
cerr << cur->second->get_fileline()
|
||||||
|
<< ": error: task and parameter in '"
|
||||||
|
<< scope->fullname() << "' have the same name '"
|
||||||
|
<< (*cur).first << "'." << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
}
|
||||||
|
|
||||||
NetScope*task_scope = new NetScope(scope, use_name,
|
NetScope*task_scope = new NetScope(scope, use_name,
|
||||||
NetScope::TASK);
|
NetScope::TASK);
|
||||||
task_scope->is_auto((*cur).second->is_auto());
|
task_scope->is_auto((*cur).second->is_auto());
|
||||||
|
|
@ -268,13 +311,39 @@ static void elaborate_scope_funcs(Design*des, NetScope*scope,
|
||||||
; cur != funcs.end() ; cur ++ ) {
|
; cur != funcs.end() ; cur ++ ) {
|
||||||
|
|
||||||
hname_t use_name( (*cur).first );
|
hname_t use_name( (*cur).first );
|
||||||
if (scope->child(use_name)) {
|
// A function can not have the same name as another scope object.
|
||||||
cerr << loc.get_fileline() << ": error: function/scope name "
|
const NetScope *child = scope->child(use_name);
|
||||||
<< use_name << " already used in this context."
|
if (child) {
|
||||||
<< endl;
|
cerr << cur->second->get_fileline()
|
||||||
|
<< ": error: function and ";
|
||||||
|
child->print_type(cerr);
|
||||||
|
cerr << " in '" << scope->fullname()
|
||||||
|
<< "' have the same name '" << use_name << "'." << endl;
|
||||||
des->errors += 1;
|
des->errors += 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A function can not have the same name as a genvar.
|
||||||
|
if (scope->find_genvar((*cur).first)) {
|
||||||
|
cerr << cur->second->get_fileline()
|
||||||
|
<< ": error: function and genvar in '"
|
||||||
|
<< scope->fullname() << "' have the same name '"
|
||||||
|
<< (*cur).first << "'." << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A function can not have the same name as a parameter.
|
||||||
|
const NetExpr *ex_msb, *ex_lsb;
|
||||||
|
const NetExpr *parm = scope->get_parameter((*cur).first, ex_msb,
|
||||||
|
ex_lsb);
|
||||||
|
if (parm) {
|
||||||
|
cerr << cur->second->get_fileline()
|
||||||
|
<< ": error: function and parameter in '"
|
||||||
|
<< scope->fullname() << "' have the same name '"
|
||||||
|
<< (*cur).first << "'." << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
}
|
||||||
|
|
||||||
NetScope*func_scope = new NetScope(scope, use_name,
|
NetScope*func_scope = new NetScope(scope, use_name,
|
||||||
NetScope::FUNC);
|
NetScope::FUNC);
|
||||||
func_scope->is_auto((*cur).second->is_auto());
|
func_scope->is_auto((*cur).second->is_auto());
|
||||||
|
|
@ -328,6 +397,12 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
|
||||||
<< scope_path(scope) << "." << endl;
|
<< scope_path(scope) << "." << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add the genvars to the scope.
|
||||||
|
typedef map<perm_string,LineInfo*>::const_iterator genvar_it_t;
|
||||||
|
for (genvar_it_t cur = genvars.begin(); cur != genvars.end(); cur++ ) {
|
||||||
|
scope->add_genvar((*cur).first, (*cur).second);
|
||||||
|
}
|
||||||
|
|
||||||
// Generate all the parameters that this instance of this
|
// Generate all the parameters that this instance of this
|
||||||
// module introduces to the design. This loop elaborates the
|
// module introduces to the design. This loop elaborates the
|
||||||
// parameters, but doesn't evaluate references to
|
// parameters, but doesn't evaluate references to
|
||||||
|
|
@ -446,6 +521,8 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
|
||||||
|
|
||||||
elaborate_scope_events_(des, scope, events);
|
elaborate_scope_events_(des, scope, events);
|
||||||
|
|
||||||
|
scope->is_cell(is_cell);
|
||||||
|
|
||||||
return des->errors == 0;
|
return des->errors == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -486,8 +563,16 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
|
||||||
{
|
{
|
||||||
// Check that the loop_index variable was declared in a
|
// Check that the loop_index variable was declared in a
|
||||||
// genvar statement.
|
// genvar statement.
|
||||||
|
NetScope*scope = container;
|
||||||
// MISSING CODE!
|
while (scope && !scope->find_genvar(loop_index))
|
||||||
|
scope = scope->parent();
|
||||||
|
if (!scope) {
|
||||||
|
cerr << get_fileline() << ": error: genvar is missing for "
|
||||||
|
"generate \"loop\" variable '" << loop_index << "'."
|
||||||
|
<< endl;
|
||||||
|
des->errors += 1;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// We're going to need a genvar...
|
// We're going to need a genvar...
|
||||||
int genvar;
|
int genvar;
|
||||||
|
|
@ -496,7 +581,9 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
|
||||||
// use) the genvar itself, so we can evaluate this expression
|
// use) the genvar itself, so we can evaluate this expression
|
||||||
// the same way any other parameter value is evaluated.
|
// the same way any other parameter value is evaluated.
|
||||||
probe_expr_width(des, container, loop_init);
|
probe_expr_width(des, container, loop_init);
|
||||||
|
need_constant_expr = true;
|
||||||
NetExpr*init_ex = elab_and_eval(des, container, loop_init, -1);
|
NetExpr*init_ex = elab_and_eval(des, container, loop_init, -1);
|
||||||
|
need_constant_expr = false;
|
||||||
NetEConst*init = dynamic_cast<NetEConst*> (init_ex);
|
NetEConst*init = dynamic_cast<NetEConst*> (init_ex);
|
||||||
if (init == 0) {
|
if (init == 0) {
|
||||||
cerr << get_fileline() << ": error: Cannot evaluate genvar"
|
cerr << get_fileline() << ": error: Cannot evaluate genvar"
|
||||||
|
|
@ -505,19 +592,53 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Since we will be adding the genvar value as a local parameter
|
// Check the generate block name.
|
||||||
// to each instances scope. We need to make sure a parameter does
|
|
||||||
// not already exist.
|
// A generate "loop" can not have the same name as another scope object.
|
||||||
const NetExpr*tmsb;
|
const NetScope *child = container->child(hname_t(scope_name));
|
||||||
const NetExpr*tlsb;
|
if (child) {
|
||||||
const NetExpr*texpr = container->get_parameter(loop_index, tmsb, tlsb);
|
cerr << get_fileline() << ": error: generate \"loop\" and ";
|
||||||
if (texpr != 0) {
|
child->print_type(cerr);
|
||||||
cerr << get_fileline() << ": error: Cannot have a genvar "
|
cerr << " in '" << container->fullname()
|
||||||
<< "and parameter with the same name: " << loop_index << endl;
|
<< "' have the same name '" << scope_name << "'." << endl;
|
||||||
des->errors += 1;
|
des->errors += 1;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A generate "loop" can not have the same name as a genvar.
|
||||||
|
if (container->find_genvar(scope_name)) {
|
||||||
|
cerr << get_fileline() << ": error: generate \"loop\" and "
|
||||||
|
"genvar in '" << container->fullname()
|
||||||
|
<< "' have the same name '" << scope_name << "'." << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A generate "loop" can not have the same name as a named event.
|
||||||
|
const NetEvent *event = container->find_event(scope_name);
|
||||||
|
if (event) {
|
||||||
|
cerr << get_fileline() << ": error: generate \"loop\" and "
|
||||||
|
"named event in '" << container->fullname()
|
||||||
|
<< "' have the same name '" << scope_name << "'." << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A generate "loop" can not have the same name as a parameter.
|
||||||
|
const NetExpr*tmsb;
|
||||||
|
const NetExpr*tlsb;
|
||||||
|
const NetExpr*texpr = container->get_parameter(scope_name, tmsb, tlsb);
|
||||||
|
if (texpr != 0) {
|
||||||
|
cerr << get_fileline() << ": error: generate \"loop\" and "
|
||||||
|
"parameter in '" << container->fullname()
|
||||||
|
<< "' have the same name '" << scope_name << "'." << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// These have all been checked so we just need to skip the actual
|
||||||
|
// generation for these name conflicts. Not skipping these two will
|
||||||
|
// cause the compiler to have problems (assert, inf. loop, etc.).
|
||||||
|
if (container->get_parameter(loop_index, tmsb, tlsb)) return false;
|
||||||
|
if (container->find_event(loop_index)) return false;
|
||||||
|
|
||||||
genvar = init->value().as_long();
|
genvar = init->value().as_long();
|
||||||
delete init_ex;
|
delete init_ex;
|
||||||
|
|
||||||
|
|
@ -526,7 +647,9 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
|
||||||
container->genvar_tmp = loop_index;
|
container->genvar_tmp = loop_index;
|
||||||
container->genvar_tmp_val = genvar;
|
container->genvar_tmp_val = genvar;
|
||||||
probe_expr_width(des, container, loop_test);
|
probe_expr_width(des, container, loop_test);
|
||||||
|
need_constant_expr = true;
|
||||||
NetExpr*test_ex = elab_and_eval(des, container, loop_test, -1);
|
NetExpr*test_ex = elab_and_eval(des, container, loop_test, -1);
|
||||||
|
need_constant_expr = false;
|
||||||
NetEConst*test = dynamic_cast<NetEConst*>(test_ex);
|
NetEConst*test = dynamic_cast<NetEConst*>(test_ex);
|
||||||
if (test == 0) {
|
if (test == 0) {
|
||||||
cerr << get_fileline() << ": error: Cannot evaluate genvar"
|
cerr << get_fileline() << ": error: Cannot evaluate genvar"
|
||||||
|
|
@ -541,13 +664,7 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
|
||||||
// container. The format of using [] is part of the
|
// container. The format of using [] is part of the
|
||||||
// Verilog standard.
|
// Verilog standard.
|
||||||
hname_t use_name (scope_name, genvar);
|
hname_t use_name (scope_name, genvar);
|
||||||
if (container->child(use_name)) {
|
|
||||||
cerr << get_fileline() << ": error: block/scope name "
|
|
||||||
<< use_name << " already used in this context."
|
|
||||||
<< endl;
|
|
||||||
des->errors += 1;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (debug_scopes)
|
if (debug_scopes)
|
||||||
cerr << get_fileline() << ": debug: "
|
cerr << get_fileline() << ": debug: "
|
||||||
<< "Create generated scope " << use_name << endl;
|
<< "Create generated scope " << use_name << endl;
|
||||||
|
|
@ -579,7 +696,9 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
|
||||||
|
|
||||||
// Calculate the step for the loop variable.
|
// Calculate the step for the loop variable.
|
||||||
probe_expr_width(des, container, loop_step);
|
probe_expr_width(des, container, loop_step);
|
||||||
|
need_constant_expr = true;
|
||||||
NetExpr*step_ex = elab_and_eval(des, container, loop_step, -1);
|
NetExpr*step_ex = elab_and_eval(des, container, loop_step, -1);
|
||||||
|
need_constant_expr = false;
|
||||||
NetEConst*step = dynamic_cast<NetEConst*>(step_ex);
|
NetEConst*step = dynamic_cast<NetEConst*>(step_ex);
|
||||||
if (step == 0) {
|
if (step == 0) {
|
||||||
cerr << get_fileline() << ": error: Cannot evaluate genvar"
|
cerr << get_fileline() << ": error: Cannot evaluate genvar"
|
||||||
|
|
@ -602,7 +721,7 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear the genvar_tmp field in the scope to reflect that the
|
// Clear the genvar_tmp field in the scope to reflect that the
|
||||||
// genvar is no longer value for evaluating expressions.
|
// genvar is no longer valid for evaluating expressions.
|
||||||
container->genvar_tmp = perm_string();
|
container->genvar_tmp = perm_string();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -611,7 +730,9 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
|
||||||
bool PGenerate::generate_scope_condit_(Design*des, NetScope*container, bool else_flag)
|
bool PGenerate::generate_scope_condit_(Design*des, NetScope*container, bool else_flag)
|
||||||
{
|
{
|
||||||
probe_expr_width(des, container, loop_test);
|
probe_expr_width(des, container, loop_test);
|
||||||
|
need_constant_expr = true;
|
||||||
NetExpr*test_ex = elab_and_eval(des, container, loop_test, -1);
|
NetExpr*test_ex = elab_and_eval(des, container, loop_test, -1);
|
||||||
|
need_constant_expr = false;
|
||||||
NetEConst*test = dynamic_cast<NetEConst*> (test_ex);
|
NetEConst*test = dynamic_cast<NetEConst*> (test_ex);
|
||||||
if (test == 0) {
|
if (test == 0) {
|
||||||
cerr << get_fileline() << ": error: Cannot evaluate genvar"
|
cerr << get_fileline() << ": error: Cannot evaluate genvar"
|
||||||
|
|
@ -634,14 +755,45 @@ bool PGenerate::generate_scope_condit_(Design*des, NetScope*container, bool else
|
||||||
}
|
}
|
||||||
|
|
||||||
hname_t use_name (scope_name);
|
hname_t use_name (scope_name);
|
||||||
if (container->child(use_name)) {
|
// A generate "if" can not have the same name as another scope object.
|
||||||
cerr << get_fileline() << ": error: block/scope name "
|
const NetScope *child = container->child(use_name);
|
||||||
<< scope_name << " already used in this context."
|
if (child) {
|
||||||
<< endl;
|
cerr << get_fileline() << ": error: generate \"if\" and ";
|
||||||
|
child->print_type(cerr);
|
||||||
|
cerr << " in '" << container->fullname()
|
||||||
|
<< "' have the same name '" << use_name << "'." << endl;
|
||||||
des->errors += 1;
|
des->errors += 1;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A generate "if" can not have the same name as a genvar.
|
||||||
|
if (container->find_genvar(scope_name)) {
|
||||||
|
cerr << get_fileline() << ": error: generate \"if\" and "
|
||||||
|
"genvar in '" << container->fullname()
|
||||||
|
<< "' have the same name '" << scope_name << "'." << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A generate "if" can not have the same name as a named event.
|
||||||
|
const NetEvent *event = container->find_event(scope_name);
|
||||||
|
if (event) {
|
||||||
|
cerr << get_fileline() << ": error: generate \"if\" and "
|
||||||
|
"named event in '" << container->fullname()
|
||||||
|
<< "' have the same name '" << use_name << "'." << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A generate "if" can not have the same name as a parameter.
|
||||||
|
const NetExpr *ex_msb, *ex_lsb;
|
||||||
|
const NetExpr *parm = container->get_parameter(scope_name, ex_msb,
|
||||||
|
ex_lsb);
|
||||||
|
if (parm) {
|
||||||
|
cerr << get_fileline() << ": error: generate \"if\" and "
|
||||||
|
"parameter in '" << container->fullname()
|
||||||
|
<< "' have the same name '" << use_name << "'." << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (debug_scopes)
|
if (debug_scopes)
|
||||||
cerr << get_fileline() << ": debug: Generate condition "
|
cerr << get_fileline() << ": debug: Generate condition "
|
||||||
<< (else_flag? "(else)" : "(if)")
|
<< (else_flag? "(else)" : "(if)")
|
||||||
|
|
@ -671,7 +823,9 @@ bool PGenerate::generate_scope_condit_(Design*des, NetScope*container, bool else
|
||||||
bool PGenerate::generate_scope_case_(Design*des, NetScope*container)
|
bool PGenerate::generate_scope_case_(Design*des, NetScope*container)
|
||||||
{
|
{
|
||||||
probe_expr_width(des, container, loop_test);
|
probe_expr_width(des, container, loop_test);
|
||||||
|
need_constant_expr = true;
|
||||||
NetExpr*case_value_ex = elab_and_eval(des, container, loop_test, -1);
|
NetExpr*case_value_ex = elab_and_eval(des, container, loop_test, -1);
|
||||||
|
need_constant_expr = false;
|
||||||
NetEConst*case_value_co = dynamic_cast<NetEConst*>(case_value_ex);
|
NetEConst*case_value_co = dynamic_cast<NetEConst*>(case_value_ex);
|
||||||
if (case_value_co == 0) {
|
if (case_value_co == 0) {
|
||||||
cerr << get_fileline() << ": error: Cannot evaluate genvar case"
|
cerr << get_fileline() << ": error: Cannot evaluate genvar case"
|
||||||
|
|
@ -702,9 +856,17 @@ bool PGenerate::generate_scope_case_(Design*des, NetScope*container)
|
||||||
bool match_flag = false;
|
bool match_flag = false;
|
||||||
for (unsigned idx = 0 ; idx < item->item_test.size() && !match_flag ; idx +=1 ) {
|
for (unsigned idx = 0 ; idx < item->item_test.size() && !match_flag ; idx +=1 ) {
|
||||||
probe_expr_width(des, container, item->item_test[idx]);
|
probe_expr_width(des, container, item->item_test[idx]);
|
||||||
|
need_constant_expr = true;
|
||||||
NetExpr*item_value_ex = elab_and_eval(des, container, item->item_test[idx], -1);
|
NetExpr*item_value_ex = elab_and_eval(des, container, item->item_test[idx], -1);
|
||||||
|
need_constant_expr = false;
|
||||||
NetEConst*item_value_co = dynamic_cast<NetEConst*>(item_value_ex);
|
NetEConst*item_value_co = dynamic_cast<NetEConst*>(item_value_ex);
|
||||||
assert(item_value_co);
|
if (item_value_co == 0) {
|
||||||
|
cerr << get_fileline() << ": error: Cannot evaluate "
|
||||||
|
<< " genvar case item expression: "
|
||||||
|
<< *item->item_test[idx] << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (debug_scopes)
|
if (debug_scopes)
|
||||||
cerr << get_fileline() << ": debug: Generate case "
|
cerr << get_fileline() << ": debug: Generate case "
|
||||||
|
|
@ -739,6 +901,44 @@ bool PGenerate::generate_scope_case_(Design*des, NetScope*container)
|
||||||
|
|
||||||
// The name of the scope to generate, whatever that item is.
|
// The name of the scope to generate, whatever that item is.
|
||||||
hname_t use_name (item->scope_name);
|
hname_t use_name (item->scope_name);
|
||||||
|
// A generate "case" can not have the same name as another scope object.
|
||||||
|
const NetScope *child = container->child(use_name);
|
||||||
|
if (child) {
|
||||||
|
cerr << get_fileline() << ": error: generate \"case\" and ";
|
||||||
|
child->print_type(cerr);
|
||||||
|
cerr << " in '" << container->fullname()
|
||||||
|
<< "' have the same name '" << use_name << "'." << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A generate "case" can not have the same name as a genvar.
|
||||||
|
if (container->find_genvar(item->scope_name)) {
|
||||||
|
cerr << get_fileline() << ": error: generate \"case\" and "
|
||||||
|
"genvar in '" << container->fullname()
|
||||||
|
<< "' have the same name '" << use_name << "'." << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A generate "case" can not have the same name as a named event.
|
||||||
|
const NetEvent *event = container->find_event(item->scope_name);
|
||||||
|
if (event) {
|
||||||
|
cerr << get_fileline() << ": error: generate \"case\" and "
|
||||||
|
"named event in '" << container->fullname()
|
||||||
|
<< "' have the same name '" << use_name << "'." << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A generate "case" can not have the same name as a parameter.
|
||||||
|
const NetExpr *ex_msb, *ex_lsb;
|
||||||
|
const NetExpr *parm = container->get_parameter(item->scope_name, ex_msb,
|
||||||
|
ex_lsb);
|
||||||
|
if (parm) {
|
||||||
|
cerr << get_fileline() << ": error: generate \"case\" and "
|
||||||
|
"parameter in '" << container->fullname()
|
||||||
|
<< "' have the same name '" << use_name << "'." << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
}
|
||||||
|
|
||||||
item->probe_for_direct_nesting_();
|
item->probe_for_direct_nesting_();
|
||||||
if (item->direct_nested_) {
|
if (item->direct_nested_) {
|
||||||
|
|
@ -760,13 +960,46 @@ bool PGenerate::generate_scope_case_(Design*des, NetScope*container)
|
||||||
bool PGenerate::generate_scope_nblock_(Design*des, NetScope*container)
|
bool PGenerate::generate_scope_nblock_(Design*des, NetScope*container)
|
||||||
{
|
{
|
||||||
hname_t use_name (scope_name);
|
hname_t use_name (scope_name);
|
||||||
if (container->child(use_name)) {
|
// A generate "block" can not have the same name as another scope
|
||||||
cerr << get_fileline() << ": error: block/scope name "
|
// object.
|
||||||
<< scope_name << " already used in this context."
|
const NetScope *child = container->child(use_name);
|
||||||
<< endl;
|
if (child) {
|
||||||
|
cerr << get_fileline() << ": error: generate \"block\" and ";
|
||||||
|
child->print_type(cerr);
|
||||||
|
cerr << " in '" << container->fullname()
|
||||||
|
<< "' have the same name '" << use_name << "'." << endl;
|
||||||
des->errors += 1;
|
des->errors += 1;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A generate "block" can not have the same name as a genvar.
|
||||||
|
if (container->find_genvar(scope_name)) {
|
||||||
|
cerr << get_fileline() << ": error: generate \"block\" and "
|
||||||
|
"genvar in '" << container->fullname()
|
||||||
|
<< "' have the same name '" << scope_name << "'." << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A generate "block" can not have the same name as a named event.
|
||||||
|
const NetEvent *event = container->find_event(scope_name);
|
||||||
|
if (event) {
|
||||||
|
cerr << get_fileline() << ": error: generate \"block\" and "
|
||||||
|
"named event in '" << container->fullname()
|
||||||
|
<< "' have the same name '" << use_name << "'." << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A generate "block" can not have the same name as a parameter.
|
||||||
|
const NetExpr *ex_msb, *ex_lsb;
|
||||||
|
const NetExpr *parm = container->get_parameter(scope_name, ex_msb,
|
||||||
|
ex_lsb);
|
||||||
|
if (parm) {
|
||||||
|
cerr << get_fileline() << ": error: generate \"block\" and "
|
||||||
|
"parameter in '" << container->fullname()
|
||||||
|
<< "' have the same name '" << use_name << "'." << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (debug_scopes)
|
if (debug_scopes)
|
||||||
cerr << get_fileline() << ": debug: Generate named block "
|
cerr << get_fileline() << ": debug: Generate named block "
|
||||||
<< ": Generate scope=" << use_name << endl;
|
<< ": Generate scope=" << use_name << endl;
|
||||||
|
|
@ -791,6 +1024,12 @@ void PGenerate::elaborate_subscope_direct_(Design*des, NetScope*scope)
|
||||||
|
|
||||||
void PGenerate::elaborate_subscope_(Design*des, NetScope*scope)
|
void PGenerate::elaborate_subscope_(Design*des, NetScope*scope)
|
||||||
{
|
{
|
||||||
|
// Add the genvars to this scope.
|
||||||
|
typedef map<perm_string,LineInfo*>::const_iterator genvar_it_t;
|
||||||
|
for (genvar_it_t cur = genvars.begin(); cur != genvars.end(); cur++ ) {
|
||||||
|
scope->add_genvar((*cur).first, (*cur).second);
|
||||||
|
}
|
||||||
|
|
||||||
// Scan the generated scope for nested generate schemes,
|
// Scan the generated scope for nested generate schemes,
|
||||||
// and *generate* new scopes, which is slightly different
|
// and *generate* new scopes, which is slightly different
|
||||||
// from simple elaboration.
|
// from simple elaboration.
|
||||||
|
|
@ -886,36 +1125,77 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
|
||||||
// Missing module instance names have already been rejected.
|
// Missing module instance names have already been rejected.
|
||||||
assert(get_name() != "");
|
assert(get_name() != "");
|
||||||
|
|
||||||
// Check for duplicate scopes. Simply look up the scope I'm
|
// A module instance can not have the same name as another scope object.
|
||||||
// about to create, and if I find it then somebody beat me to
|
const NetScope *child = sc->child(hname_t(get_name()));
|
||||||
// it.
|
if (child) {
|
||||||
|
cerr << get_fileline() << ": error: module <" << mod->mod_name()
|
||||||
if (sc->child(hname_t(get_name()))) {
|
<< "> instance and ";
|
||||||
cerr << get_fileline() << ": error: Instance/Scope name " <<
|
child->print_type(cerr);
|
||||||
get_name() << " already used in this context." <<
|
cerr << " in '" << sc->fullname()
|
||||||
endl;
|
<< "' have the same name '" << get_name() << "'." << endl;
|
||||||
des->errors += 1;
|
des->errors += 1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A module instance can not have the same name as a genvar.
|
||||||
|
if (sc->find_genvar(get_name())) {
|
||||||
|
cerr << get_fileline() << ": error: module <" << mod->mod_name()
|
||||||
|
<< "> instance and genvar in '" << sc->fullname()
|
||||||
|
<< "' have the same name '" << get_name() << "'." << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A module instance can not have the same name as a parameter.
|
||||||
|
const NetExpr *ex_msb, *ex_lsb;
|
||||||
|
const NetExpr *parm = sc->get_parameter(get_name(), ex_msb, ex_lsb);
|
||||||
|
if (parm) {
|
||||||
|
cerr << get_fileline() << ": error: module <" << mod->mod_name()
|
||||||
|
<< "> instance and parameter in '" << sc->fullname()
|
||||||
|
<< "' have the same name '" << get_name() << "'." << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
}
|
||||||
|
|
||||||
// check for recursive instantiation by scanning the current
|
// check for recursive instantiation by scanning the current
|
||||||
// scope and its parents. Look for a module instantiation of
|
// scope and its parents. Look for a module instantiation of
|
||||||
// the same module, but farther up in the scope.
|
// the same module, but farther up in the scope.
|
||||||
|
unsigned rl_count = 0;
|
||||||
|
bool in_genblk = false;
|
||||||
for (NetScope*scn = sc ; scn ; scn = scn->parent()) {
|
for (NetScope*scn = sc ; scn ; scn = scn->parent()) {
|
||||||
if (scn->type() != NetScope::MODULE)
|
// We need to know if we are inside a generate block to allow
|
||||||
|
// recursive instances.
|
||||||
|
if (scn->type() == NetScope::GENBLOCK) {
|
||||||
|
in_genblk = true;
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (strcmp(mod->mod_name(), scn->module_name()) != 0)
|
if (scn->type() != NetScope::MODULE) continue;
|
||||||
|
|
||||||
|
if (strcmp(mod->mod_name(), scn->module_name()) != 0) continue;
|
||||||
|
|
||||||
|
// We allow nested scopes if they are inside a generate block,
|
||||||
|
// but only to a certain nesting depth.
|
||||||
|
if (in_genblk) {
|
||||||
|
rl_count += 1;
|
||||||
|
if (rl_count > recursive_mod_limit) {
|
||||||
|
cerr << get_fileline() << ": error: instance "
|
||||||
|
<< scope_path(sc) << "." << get_name()
|
||||||
|
<< " of module " << mod->mod_name()
|
||||||
|
<< " is nested too deep." << endl;
|
||||||
|
cerr << get_fileline() << ": : check for "
|
||||||
|
"proper recursion termination or increase the "
|
||||||
|
"limit (" << recursive_mod_limit
|
||||||
|
<< ") with the -pRECURSIVE_MOD_LIMIT flag."
|
||||||
|
<< endl;
|
||||||
|
des->errors += 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
cerr << get_fileline() << ": error: You cannot instantiate "
|
cerr << get_fileline() << ": error: You cannot instantiate "
|
||||||
<< "module " << mod->mod_name() << " within itself." << endl;
|
<< "module " << mod->mod_name() << " within itself." << endl;
|
||||||
|
|
||||||
cerr << get_fileline() << ": : The offending instance is "
|
cerr << get_fileline() << ": : The offending instance is "
|
||||||
<< scope_path(sc) << "." << get_name() << " within "
|
<< get_name() << " within " << scope_path(scn) << "." << endl;
|
||||||
<< scope_path(scn) << "." << endl;
|
|
||||||
|
|
||||||
des->errors += 1;
|
des->errors += 1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -952,8 +1232,10 @@ void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*s
|
||||||
{
|
{
|
||||||
if (msb_) probe_expr_width(des, sc, msb_);
|
if (msb_) probe_expr_width(des, sc, msb_);
|
||||||
if (lsb_) probe_expr_width(des, sc, lsb_);
|
if (lsb_) probe_expr_width(des, sc, lsb_);
|
||||||
|
need_constant_expr = true;
|
||||||
NetExpr*mse = msb_ ? elab_and_eval(des, sc, msb_, -1) : 0;
|
NetExpr*mse = msb_ ? elab_and_eval(des, sc, msb_, -1) : 0;
|
||||||
NetExpr*lse = lsb_ ? elab_and_eval(des, sc, lsb_, -1) : 0;
|
NetExpr*lse = lsb_ ? elab_and_eval(des, sc, lsb_, -1) : 0;
|
||||||
|
need_constant_expr = false;
|
||||||
NetEConst*msb = dynamic_cast<NetEConst*> (mse);
|
NetEConst*msb = dynamic_cast<NetEConst*> (mse);
|
||||||
NetEConst*lsb = dynamic_cast<NetEConst*> (lse);
|
NetEConst*lsb = dynamic_cast<NetEConst*> (lse);
|
||||||
|
|
||||||
|
|
@ -1019,6 +1301,7 @@ void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*s
|
||||||
// Set time units and precision.
|
// Set time units and precision.
|
||||||
my_scope->time_unit(mod->time_unit);
|
my_scope->time_unit(mod->time_unit);
|
||||||
my_scope->time_precision(mod->time_precision);
|
my_scope->time_precision(mod->time_precision);
|
||||||
|
my_scope->time_from_timescale(mod->time_from_timescale);
|
||||||
des->set_precision(mod->time_precision);
|
des->set_precision(mod->time_precision);
|
||||||
|
|
||||||
// Look for module parameter replacements. The "replace" map
|
// Look for module parameter replacements. The "replace" map
|
||||||
|
|
@ -1109,6 +1392,34 @@ void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*s
|
||||||
*/
|
*/
|
||||||
void PEvent::elaborate_scope(Design*des, NetScope*scope) const
|
void PEvent::elaborate_scope(Design*des, NetScope*scope) const
|
||||||
{
|
{
|
||||||
|
// A named event can not have the same name as another scope object.
|
||||||
|
const NetScope *child = scope->child(hname_t(name_));
|
||||||
|
if (child) {
|
||||||
|
cerr << get_fileline() << ": error: named event and ";
|
||||||
|
child->print_type(cerr);
|
||||||
|
cerr << " in '" << scope->fullname()
|
||||||
|
<< "' have the same name '" << name_ << "'." << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A named event can not have the same name as a genvar.
|
||||||
|
if (scope->find_genvar(name_)) {
|
||||||
|
cerr << get_fileline() << ": error: named event and "
|
||||||
|
<< "genvar in '" << scope->fullname()
|
||||||
|
<< "' have the same name '" << name_ << "'." << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A named event can not have the same name as a parameter.
|
||||||
|
const NetExpr *ex_msb, *ex_lsb;
|
||||||
|
const NetExpr *parm = scope->get_parameter(name_, ex_msb, ex_lsb);
|
||||||
|
if (parm) {
|
||||||
|
cerr << get_fileline() << ": error: named event and "
|
||||||
|
<< "parameter in '" << scope->fullname()
|
||||||
|
<< "' have the same name '" << name_ << "'." << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
}
|
||||||
|
|
||||||
NetEvent*ev = new NetEvent(name_);
|
NetEvent*ev = new NetEvent(name_);
|
||||||
ev->set_line(*this);
|
ev->set_line(*this);
|
||||||
scope->add_event(ev);
|
scope->add_event(ev);
|
||||||
|
|
@ -1189,13 +1500,37 @@ void PBlock::elaborate_scope(Design*des, NetScope*scope) const
|
||||||
|
|
||||||
if (pscope_name() != 0) {
|
if (pscope_name() != 0) {
|
||||||
hname_t use_name(pscope_name());
|
hname_t use_name(pscope_name());
|
||||||
if (scope->child(use_name)) {
|
// A named block can not have the same name as another scope
|
||||||
cerr << get_fileline() << ": error: block/scope name "
|
// object.
|
||||||
<< use_name << " already used in this context."
|
const NetScope *child = scope->child(use_name);
|
||||||
<< endl;
|
if (child) {
|
||||||
|
cerr << get_fileline() << ": error: named block and ";
|
||||||
|
child->print_type(cerr);
|
||||||
|
cerr << " in '" << scope->fullname()
|
||||||
|
<< "' have the same name '" << use_name << "'." << endl;
|
||||||
des->errors += 1;
|
des->errors += 1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A named block can not have the same name as a genvar.
|
||||||
|
if (scope->find_genvar(pscope_name())) {
|
||||||
|
cerr << get_fileline() << ": error: named block and "
|
||||||
|
"genvar in '" << scope->fullname()
|
||||||
|
<< "' have the same name '" << use_name << "'." << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A named block can not have the same name as a parameter.
|
||||||
|
const NetExpr *ex_msb, *ex_lsb;
|
||||||
|
const NetExpr *parm = scope->get_parameter(pscope_name(), ex_msb,
|
||||||
|
ex_lsb);
|
||||||
|
if (parm) {
|
||||||
|
cerr << get_fileline() << ": error: named block and "
|
||||||
|
"parameter in '" << scope->fullname()
|
||||||
|
<< "' have the same name '" << use_name << "'." << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (debug_scopes)
|
if (debug_scopes)
|
||||||
cerr << get_fileline() << ": debug: "
|
cerr << get_fileline() << ": debug: "
|
||||||
<< "Elaborate block scope " << use_name
|
<< "Elaborate block scope " << use_name
|
||||||
|
|
|
||||||
68
elab_sig.cc
68
elab_sig.cc
|
|
@ -126,7 +126,7 @@ static void elaborate_sig_funcs(Design*des, NetScope*scope,
|
||||||
|
|
||||||
hname_t use_name ( (*cur).first );
|
hname_t use_name ( (*cur).first );
|
||||||
NetScope*fscope = scope->child(use_name);
|
NetScope*fscope = scope->child(use_name);
|
||||||
if (scope == 0) {
|
if (fscope == 0) {
|
||||||
cerr << (*cur).second->get_fileline() << ": internal error: "
|
cerr << (*cur).second->get_fileline() << ": internal error: "
|
||||||
<< "Child scope for function " << (*cur).first
|
<< "Child scope for function " << (*cur).first
|
||||||
<< " missing in " << scope_path(scope) << "." << endl;
|
<< " missing in " << scope_path(scope) << "." << endl;
|
||||||
|
|
@ -599,9 +599,11 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
||||||
}
|
}
|
||||||
|
|
||||||
ret_sig = new NetNet(scope, fname, NetNet::REG, mnum, lnum);
|
ret_sig = new NetNet(scope, fname, NetNet::REG, mnum, lnum);
|
||||||
|
ret_sig->set_scalar(false);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
ret_sig = new NetNet(scope, fname, NetNet::REG);
|
ret_sig = new NetNet(scope, fname, NetNet::REG);
|
||||||
|
ret_sig->set_scalar(true);
|
||||||
}
|
}
|
||||||
ret_sig->set_line(*this);
|
ret_sig->set_line(*this);
|
||||||
ret_sig->set_signed(return_type_.type == PTF_REG_S);
|
ret_sig->set_signed(return_type_.type == PTF_REG_S);
|
||||||
|
|
@ -614,6 +616,7 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
||||||
ret_sig->set_line(*this);
|
ret_sig->set_line(*this);
|
||||||
ret_sig->set_signed(true);
|
ret_sig->set_signed(true);
|
||||||
ret_sig->set_isint(true);
|
ret_sig->set_isint(true);
|
||||||
|
ret_sig->set_scalar(false);
|
||||||
ret_sig->port_type(NetNet::POUTPUT);
|
ret_sig->port_type(NetNet::POUTPUT);
|
||||||
ret_sig->data_type(IVL_VT_LOGIC);
|
ret_sig->data_type(IVL_VT_LOGIC);
|
||||||
break;
|
break;
|
||||||
|
|
@ -623,6 +626,7 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
||||||
ret_sig->set_line(*this);
|
ret_sig->set_line(*this);
|
||||||
ret_sig->set_signed(false);
|
ret_sig->set_signed(false);
|
||||||
ret_sig->set_isint(false);
|
ret_sig->set_isint(false);
|
||||||
|
ret_sig->set_scalar(false);
|
||||||
ret_sig->port_type(NetNet::POUTPUT);
|
ret_sig->port_type(NetNet::POUTPUT);
|
||||||
ret_sig->data_type(IVL_VT_LOGIC);
|
ret_sig->data_type(IVL_VT_LOGIC);
|
||||||
break;
|
break;
|
||||||
|
|
@ -633,6 +637,7 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
||||||
ret_sig->set_line(*this);
|
ret_sig->set_line(*this);
|
||||||
ret_sig->set_signed(true);
|
ret_sig->set_signed(true);
|
||||||
ret_sig->set_isint(false);
|
ret_sig->set_isint(false);
|
||||||
|
ret_sig->set_scalar(true);
|
||||||
ret_sig->port_type(NetNet::POUTPUT);
|
ret_sig->port_type(NetNet::POUTPUT);
|
||||||
ret_sig->data_type(IVL_VT_REAL);
|
ret_sig->data_type(IVL_VT_REAL);
|
||||||
break;
|
break;
|
||||||
|
|
@ -843,23 +848,63 @@ void PWhile::elaborate_sig(Design*des, NetScope*scope) const
|
||||||
/*
|
/*
|
||||||
* Elaborate a source wire. The "wire" is the declaration of wires,
|
* Elaborate a source wire. The "wire" is the declaration of wires,
|
||||||
* registers, ports and memories. The parser has already merged the
|
* registers, ports and memories. The parser has already merged the
|
||||||
* multiple properties of a wire (i.e., "input wire") so come the
|
* multiple properties of a wire (i.e., "input wire"), so come the
|
||||||
* elaboration this creates an object in the design that represent the
|
* elaboration this creates an object in the design that represents the
|
||||||
* defined item.
|
* defined item.
|
||||||
*/
|
*/
|
||||||
NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||||
{
|
{
|
||||||
NetNet::Type wtype = type_;
|
NetNet::Type wtype = type_;
|
||||||
if (wtype == NetNet::IMPLICIT)
|
bool is_implicit_scalar = false;
|
||||||
|
if (wtype == NetNet::IMPLICIT) {
|
||||||
wtype = NetNet::WIRE;
|
wtype = NetNet::WIRE;
|
||||||
if (wtype == NetNet::IMPLICIT_REG)
|
is_implicit_scalar = true;
|
||||||
|
}
|
||||||
|
if (wtype == NetNet::IMPLICIT_REG) {
|
||||||
wtype = NetNet::REG;
|
wtype = NetNet::REG;
|
||||||
|
is_implicit_scalar = true;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned wid = 1;
|
unsigned wid = 1;
|
||||||
long lsb = 0, msb = 0;
|
long lsb = 0, msb = 0;
|
||||||
|
|
||||||
des->errors += error_cnt_;
|
des->errors += error_cnt_;
|
||||||
|
|
||||||
|
// A signal can not have the same name as a scope object.
|
||||||
|
const NetScope *child = scope->child(hname_t(name_));
|
||||||
|
if (child) {
|
||||||
|
cerr << get_fileline() << ": error: signal and ";
|
||||||
|
child->print_type(cerr);
|
||||||
|
cerr << " in '" << scope->fullname()
|
||||||
|
<< "' have the same name '" << name_ << "'." << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
}
|
||||||
|
// A signal can not have the same name as a genvar.
|
||||||
|
const LineInfo *genvar = scope->find_genvar(name_);
|
||||||
|
if (genvar) {
|
||||||
|
cerr << get_fileline() << ": error: signal and genvar in '"
|
||||||
|
<< scope->fullname() << "' have the same name '" << name_
|
||||||
|
<< "'." << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
}
|
||||||
|
// A signal can not have the same name as a parameter.
|
||||||
|
const NetExpr *ex_msb, *ex_lsb;
|
||||||
|
const NetExpr *parm = scope->get_parameter(name_, ex_msb, ex_lsb);
|
||||||
|
if (parm) {
|
||||||
|
cerr << get_fileline() << ": error: signal and parameter in '"
|
||||||
|
<< scope->fullname() << "' have the same name '" << name_
|
||||||
|
<< "'." << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
}
|
||||||
|
// A signal can not have the same name as a named event.
|
||||||
|
const NetEvent *event = scope->find_event(name_);
|
||||||
|
if (event) {
|
||||||
|
cerr << get_fileline() << ": error: signal and named event in '"
|
||||||
|
<< scope->fullname() << "' have the same name '" << name_
|
||||||
|
<< "'." << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (port_set_ || net_set_) {
|
if (port_set_ || net_set_) {
|
||||||
long pmsb = 0, plsb = 0, nmsb = 0, nlsb = 0;
|
long pmsb = 0, plsb = 0, nmsb = 0, nlsb = 0;
|
||||||
bool bad_lsb = false, bad_msb = false;
|
bool bad_lsb = false, bad_msb = false;
|
||||||
|
|
@ -902,6 +947,8 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||||
delete texpr;
|
delete texpr;
|
||||||
nmsb = pmsb;
|
nmsb = pmsb;
|
||||||
nlsb = plsb;
|
nlsb = plsb;
|
||||||
|
/* An implicit port can have a range so note that here. */
|
||||||
|
is_implicit_scalar = false;
|
||||||
}
|
}
|
||||||
if (!port_set_) assert(port_msb_ == 0 && port_lsb_ == 0);
|
if (!port_set_) assert(port_msb_ == 0 && port_lsb_ == 0);
|
||||||
if (port_msb_ == 0) assert(port_lsb_ == 0);
|
if (port_msb_ == 0) assert(port_lsb_ == 0);
|
||||||
|
|
@ -1095,8 +1142,11 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||||
}
|
}
|
||||||
|
|
||||||
if (debug_elaborate) {
|
if (debug_elaborate) {
|
||||||
cerr << get_fileline() << ": debug: Create signal "
|
cerr << get_fileline() << ": debug: Create signal " << wtype;
|
||||||
<< wtype << " ["<<msb<<":"<<lsb<<"] " << name_;
|
if (!get_scalar()) {
|
||||||
|
cerr << " ["<<msb<<":"<<lsb<<"]";
|
||||||
|
}
|
||||||
|
cerr << " " << name_;
|
||||||
if (array_dimensions > 0) {
|
if (array_dimensions > 0) {
|
||||||
cerr << " [" << array_s0 << ":" << array_e0 << "]" << endl;
|
cerr << " [" << array_s0 << ":" << array_e0 << "]" << endl;
|
||||||
}
|
}
|
||||||
|
|
@ -1108,6 +1158,8 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||||
? new NetNet(scope, name_, wtype, msb, lsb, array_s0, array_e0)
|
? new NetNet(scope, name_, wtype, msb, lsb, array_s0, array_e0)
|
||||||
: new NetNet(scope, name_, wtype, msb, lsb);
|
: new NetNet(scope, name_, wtype, msb, lsb);
|
||||||
|
|
||||||
|
if (wtype == NetNet::WIRE) sig->devirtualize_pins();
|
||||||
|
|
||||||
ivl_variable_type_t use_data_type = data_type_;
|
ivl_variable_type_t use_data_type = data_type_;
|
||||||
if (use_data_type == IVL_VT_NO_TYPE) {
|
if (use_data_type == IVL_VT_NO_TYPE) {
|
||||||
use_data_type = IVL_VT_LOGIC;
|
use_data_type = IVL_VT_LOGIC;
|
||||||
|
|
@ -1124,6 +1176,8 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||||
sig->port_type(port_type_);
|
sig->port_type(port_type_);
|
||||||
sig->set_signed(get_signed());
|
sig->set_signed(get_signed());
|
||||||
sig->set_isint(get_isint());
|
sig->set_isint(get_isint());
|
||||||
|
if (is_implicit_scalar) sig->set_scalar(true);
|
||||||
|
else sig->set_scalar(get_scalar());
|
||||||
|
|
||||||
if (ivl_discipline_t dis = get_discipline()) {
|
if (ivl_discipline_t dis = get_discipline()) {
|
||||||
sig->set_discipline(dis);
|
sig->set_discipline(dis);
|
||||||
|
|
|
||||||
197
elaborate.cc
197
elaborate.cc
|
|
@ -189,6 +189,14 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
|
||||||
need_driver_flag = false;
|
need_driver_flag = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* When we are given a non-default strength value and if the
|
||||||
|
* drive source is a bit, part or indexed select we need to
|
||||||
|
* add a driver (BUFZ) to convey the strength information. */
|
||||||
|
if ((drive0 != Link::STRONG || drive1 != Link::STRONG) &&
|
||||||
|
(dynamic_cast<NetESelect*>(rval_expr))) {
|
||||||
|
need_driver_flag = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (need_driver_flag) {
|
if (need_driver_flag) {
|
||||||
NetBUFZ*driver = new NetBUFZ(scope, scope->local_symbol(),
|
NetBUFZ*driver = new NetBUFZ(scope, scope->local_symbol(),
|
||||||
rval->vector_width());
|
rval->vector_width());
|
||||||
|
|
@ -234,8 +242,10 @@ unsigned PGBuiltin::calculate_array_count_(Design*des, NetScope*scope,
|
||||||
gates, then I am expected to make more than one
|
gates, then I am expected to make more than one
|
||||||
gate. Figure out how many are desired. */
|
gate. Figure out how many are desired. */
|
||||||
if (msb_) {
|
if (msb_) {
|
||||||
|
need_constant_expr = true;
|
||||||
NetExpr*msb_exp = elab_and_eval(des, scope, msb_, -1);
|
NetExpr*msb_exp = elab_and_eval(des, scope, msb_, -1);
|
||||||
NetExpr*lsb_exp = elab_and_eval(des, scope, lsb_, -1);
|
NetExpr*lsb_exp = elab_and_eval(des, scope, lsb_, -1);
|
||||||
|
need_constant_expr = false;
|
||||||
|
|
||||||
NetEConst*msb_con = dynamic_cast<NetEConst*>(msb_exp);
|
NetEConst*msb_con = dynamic_cast<NetEConst*>(msb_exp);
|
||||||
NetEConst*lsb_con = dynamic_cast<NetEConst*>(lsb_exp);
|
NetEConst*lsb_con = dynamic_cast<NetEConst*>(lsb_exp);
|
||||||
|
|
@ -623,7 +633,9 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
lval_sigs[idx] = pin(idx)->elaborate_lnet(des, scope);
|
lval_sigs[idx] = pin(idx)->elaborate_lnet(des, scope);
|
||||||
ivl_assert(*this, lval_sigs[idx]);
|
// The only way this should return zero is if an error
|
||||||
|
// happened, so for that case just return.
|
||||||
|
if (lval_sigs[idx] == 0) return;
|
||||||
|
|
||||||
// For now, assume all the outputs are the same width.
|
// For now, assume all the outputs are the same width.
|
||||||
ivl_assert(*this, idx == 0 || lval_sigs[idx]->vector_width() == lval_sigs[0]->vector_width());
|
ivl_assert(*this, idx == 0 || lval_sigs[idx]->vector_width() == lval_sigs[0]->vector_width());
|
||||||
|
|
@ -966,6 +978,28 @@ static bool need_bufz_for_input_port(const vector<NetNet*>&prts)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Convert a wire or tri to a tri0 or tri1 as needed to make
|
||||||
|
* an unconnected drive pull for floating inputs.
|
||||||
|
*/
|
||||||
|
static void convert_net(Design*des, const LineInfo *line,
|
||||||
|
NetNet *net, NetNet::Type type)
|
||||||
|
{
|
||||||
|
// If the types already match just return.
|
||||||
|
if (net->type() == type) return;
|
||||||
|
|
||||||
|
// We can only covert a wire or tri to have a default pull.
|
||||||
|
if (net->type() == NetNet::WIRE || net->type() == NetNet::TRI) {
|
||||||
|
net->type(type);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We may have to support this at some point in time!
|
||||||
|
cerr << line->get_fileline() << ": sorry: Can not pull floating "
|
||||||
|
"input type '" << net->type() << "'." << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Instantiate a module by recursively elaborating it. Set the path of
|
* Instantiate a module by recursively elaborating it. Set the path of
|
||||||
* the recursive elaboration so that signal names get properly
|
* the recursive elaboration so that signal names get properly
|
||||||
|
|
@ -1058,7 +1092,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
||||||
|
|
||||||
// No named bindings, just use the positional list I
|
// No named bindings, just use the positional list I
|
||||||
// already have.
|
// already have.
|
||||||
assert(pin_count() == rmod->port_count());
|
ivl_assert(*this, pin_count() == rmod->port_count());
|
||||||
pins = get_pins();
|
pins = get_pins();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1093,28 +1127,50 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
||||||
// null parameter is passed in.
|
// null parameter is passed in.
|
||||||
|
|
||||||
if (pins[idx] == 0) {
|
if (pins[idx] == 0) {
|
||||||
|
// We need this information to support the
|
||||||
|
// unconnected_drive directive and for a
|
||||||
|
// unconnected input warning when asked for.
|
||||||
|
vector<PEIdent*> mport = rmod->get_port(idx);
|
||||||
|
if (mport.size() == 0) continue;
|
||||||
|
|
||||||
// While we're here, look to see if this
|
perm_string pname = peek_tail_name(mport[0]->path());
|
||||||
// unconnected (from the outside) port is an
|
|
||||||
// input. If so, consider printing a port binding
|
|
||||||
// warning.
|
|
||||||
if (warn_portbinding) {
|
|
||||||
vector<PEIdent*> mport = rmod->get_port(idx);
|
|
||||||
if (mport.size() == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
perm_string pname = peek_tail_name(mport[0]->path());
|
NetNet*tmp = instance[0]->find_signal(pname);
|
||||||
|
ivl_assert(*this, tmp);
|
||||||
|
|
||||||
NetNet*tmp = instance[0]->find_signal(pname);
|
if (tmp->port_type() == NetNet::PINPUT) {
|
||||||
assert(tmp);
|
// If we have an unconnected input convert it
|
||||||
|
// as needed if an unconnected_drive directive
|
||||||
|
// was given. This only works for tri or wire!
|
||||||
|
switch (rmod->uc_drive) {
|
||||||
|
case Module::UCD_PULL0:
|
||||||
|
convert_net(des, this, tmp, NetNet::TRI0);
|
||||||
|
break;
|
||||||
|
case Module::UCD_PULL1:
|
||||||
|
convert_net(des, this, tmp, NetNet::TRI1);
|
||||||
|
break;
|
||||||
|
case Module::UCD_NONE:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (tmp->port_type() == NetNet::PINPUT) {
|
// Print a waring for an unconnected input.
|
||||||
|
if (warn_portbinding) {
|
||||||
cerr << get_fileline() << ": warning: "
|
cerr << get_fileline() << ": warning: "
|
||||||
<< "Instantiating module "
|
<< "Instantiating module "
|
||||||
<< rmod->mod_name()
|
<< rmod->mod_name()
|
||||||
<< " with dangling input port "
|
<< " with dangling input port '"
|
||||||
<< rmod->ports[idx]->name
|
<< rmod->ports[idx]->name;
|
||||||
<< "." << endl;
|
switch (rmod->uc_drive) {
|
||||||
|
case Module::UCD_PULL0:
|
||||||
|
cerr << "' (pulled low)." << endl;
|
||||||
|
break;
|
||||||
|
case Module::UCD_PULL1:
|
||||||
|
cerr << "' (pulled high)." << endl;
|
||||||
|
break;
|
||||||
|
case Module::UCD_NONE:
|
||||||
|
cerr << "' (floating)." << endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1146,13 +1202,13 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
||||||
for (unsigned ldx = 0 ; ldx < mport.size() ; ldx += 1) {
|
for (unsigned ldx = 0 ; ldx < mport.size() ; ldx += 1) {
|
||||||
unsigned lbase = inst * mport.size();
|
unsigned lbase = inst * mport.size();
|
||||||
PEIdent*pport = mport[ldx];
|
PEIdent*pport = mport[ldx];
|
||||||
assert(pport);
|
ivl_assert(*this, pport);
|
||||||
prts[lbase + ldx]
|
prts[lbase + ldx]
|
||||||
= pport->elaborate_port(des, inst_scope);
|
= pport->elaborate_port(des, inst_scope);
|
||||||
if (prts[lbase + ldx] == 0)
|
if (prts[lbase + ldx] == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
assert(prts[lbase + ldx]);
|
ivl_assert(*this, prts[lbase + ldx]);
|
||||||
prts_vector_width += prts[lbase + ldx]->vector_width();
|
prts_vector_width += prts[lbase + ldx]->vector_width();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1167,7 +1223,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
||||||
// We know by design that each instance has the same
|
// We know by design that each instance has the same
|
||||||
// width port. Therefore, the prts_pin_count must be an
|
// width port. Therefore, the prts_pin_count must be an
|
||||||
// even multiple of the instance count.
|
// even multiple of the instance count.
|
||||||
assert(prts_vector_width % instance.size() == 0);
|
ivl_assert(*this, prts_vector_width % instance.size() == 0);
|
||||||
|
|
||||||
unsigned desired_vector_width = prts_vector_width;
|
unsigned desired_vector_width = prts_vector_width;
|
||||||
if (instance.size() != 1)
|
if (instance.size() != 1)
|
||||||
|
|
@ -1284,12 +1340,12 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(sig);
|
ivl_assert(*this, sig);
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if ((prts.size() >= 1)
|
if ((prts.size() >= 1)
|
||||||
&& (prts[0]->port_type() != NetNet::PINPUT)) {
|
&& (prts[0]->port_type() != NetNet::PINPUT)) {
|
||||||
assert(sig->type() != NetNet::REG);
|
ivl_assert(*this, sig->type() != NetNet::REG);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -1515,43 +1571,34 @@ void PGModule::elaborate_udp_(Design*des, PUdp*udp, NetScope*scope) const
|
||||||
module or primitive, it interprets them as parameter
|
module or primitive, it interprets them as parameter
|
||||||
overrides. Correct that misconception here. */
|
overrides. Correct that misconception here. */
|
||||||
if (overrides_) {
|
if (overrides_) {
|
||||||
PDelays tmp_del;
|
if (overrides_->count() > 2) {
|
||||||
tmp_del.set_delays(overrides_, false);
|
cerr << get_fileline() << ": error: UDPs take at most two "
|
||||||
tmp_del.eval_delays(des, scope, rise_expr, fall_expr, decay_expr);
|
"delay arguments." << endl;
|
||||||
|
|
||||||
if (dynamic_cast<NetEConst*> (rise_expr)) {
|
|
||||||
|
|
||||||
} else {
|
|
||||||
cerr << get_fileline() << ": error: Delay expressions must be "
|
|
||||||
<< "constant for primitives." << endl;
|
|
||||||
cerr << get_fileline() << ": : Cannot calculate "
|
|
||||||
<< *rise_expr << endl;
|
|
||||||
des->errors += 1;
|
des->errors += 1;
|
||||||
}
|
|
||||||
|
|
||||||
if (dynamic_cast<NetEConst*> (fall_expr)) {
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
cerr << get_fileline() << ": error: Delay expressions must be "
|
PDelays tmp_del;
|
||||||
<< "constant for primitives." << endl;
|
tmp_del.set_delays(overrides_, false);
|
||||||
cerr << get_fileline() << ": : Cannot calculate "
|
tmp_del.eval_delays(des, scope, rise_expr, fall_expr,
|
||||||
<< *rise_expr << endl;
|
decay_expr);
|
||||||
des->errors += 1;
|
|
||||||
|
if (! dynamic_cast<NetEConst*> (rise_expr)) {
|
||||||
|
cerr << get_fileline() << ": error: UDP rising delay "
|
||||||
|
"expression must be constant." << endl;
|
||||||
|
cerr << get_fileline() << ": : Cannot calculate "
|
||||||
|
<< *rise_expr << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! dynamic_cast<NetEConst*> (fall_expr)) {
|
||||||
|
cerr << get_fileline() << ": error: UDP falling delay "
|
||||||
|
"expression must be constant." << endl;
|
||||||
|
cerr << get_fileline() << ": : Cannot calculate "
|
||||||
|
<< *fall_expr << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dynamic_cast<NetEConst*> (decay_expr)) {
|
|
||||||
|
|
||||||
} else {
|
|
||||||
cerr << get_fileline() << ": error: Delay expressions must be "
|
|
||||||
<< "constant for primitives." << endl;
|
|
||||||
cerr << get_fileline() << ": : Cannot calculate "
|
|
||||||
<< *rise_expr << endl;
|
|
||||||
des->errors += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
assert(udp);
|
assert(udp);
|
||||||
NetUDP*net = new NetUDP(scope, my_name, udp->ports.count(), udp);
|
NetUDP*net = new NetUDP(scope, my_name, udp->ports.count(), udp);
|
||||||
net->rise_time(rise_expr);
|
net->rise_time(rise_expr);
|
||||||
|
|
@ -1815,6 +1862,20 @@ static NetExpr*elaborate_delay_expr(PExpr*expr, Design*des, NetScope*scope)
|
||||||
probe_expr_width(des, scope, expr);
|
probe_expr_width(des, scope, expr);
|
||||||
NetExpr*dex = elab_and_eval(des, scope, expr, -1);
|
NetExpr*dex = elab_and_eval(des, scope, expr, -1);
|
||||||
|
|
||||||
|
/* Print a warning if we find default and `timescale based
|
||||||
|
* delays in the design, since this is likely an error. */
|
||||||
|
if (scope->time_from_timescale()) dly_used_timescale = true;
|
||||||
|
else dly_used_no_timescale = true;
|
||||||
|
|
||||||
|
if (display_ts_dly_warning &&
|
||||||
|
dly_used_no_timescale && dly_used_timescale) {
|
||||||
|
cerr << "warning: Found both default and "
|
||||||
|
"`timescale based delays. Use" << endl;
|
||||||
|
cerr << " -Wtimescale to find the "
|
||||||
|
"module(s) with no `timescale." << endl;
|
||||||
|
display_ts_dly_warning = false;
|
||||||
|
}
|
||||||
|
|
||||||
/* If the delay expression is a real constant or vector
|
/* If the delay expression is a real constant or vector
|
||||||
constant, then evaluate it, scale it to the local time
|
constant, then evaluate it, scale it to the local time
|
||||||
units, and return an adjusted NetEConst. */
|
units, and return an adjusted NetEConst. */
|
||||||
|
|
@ -2583,6 +2644,13 @@ NetProc* PCallTask::elaborate_usr(Design*des, NetScope*scope) const
|
||||||
ivl_variable_type_t lv_type = lv->expr_type();
|
ivl_variable_type_t lv_type = lv->expr_type();
|
||||||
|
|
||||||
NetExpr*rv = elaborate_rval_expr(des, scope, lv_type, wid, parms_[idx]);
|
NetExpr*rv = elaborate_rval_expr(des, scope, lv_type, wid, parms_[idx]);
|
||||||
|
if (NetEEvent*evt = dynamic_cast<NetEEvent*> (rv)) {
|
||||||
|
cerr << evt->get_fileline() << ": error: An event '"
|
||||||
|
<< evt->event()->name() << "' can not be a user "
|
||||||
|
"task argument." << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (wid > rv->expr_width()) {
|
if (wid > rv->expr_width()) {
|
||||||
rv->set_width(wid);
|
rv->set_width(wid);
|
||||||
rv = pad_to_width(rv, wid, *this);
|
rv = pad_to_width(rv, wid, *this);
|
||||||
|
|
@ -3716,15 +3784,26 @@ void PSpecPath::elaborate(Design*des, NetScope*scope) const
|
||||||
|
|
||||||
/* Do not elaborate specify delay paths if this feature is
|
/* Do not elaborate specify delay paths if this feature is
|
||||||
turned off. */
|
turned off. */
|
||||||
if (!gn_specify_blocks_flag)
|
if (!gn_specify_blocks_flag) return;
|
||||||
return;
|
|
||||||
|
|
||||||
ivl_assert(*this, conditional || (condition==0));
|
ivl_assert(*this, conditional || (condition==0));
|
||||||
|
|
||||||
ndelays = delays.size();
|
ndelays = delays.size();
|
||||||
if (ndelays > 12)
|
if (ndelays > 12) ndelays = 12;
|
||||||
ndelays = 12;
|
|
||||||
|
|
||||||
|
/* Print a warning if we find default and `timescale based
|
||||||
|
* delays in the design, since this is likely an error. */
|
||||||
|
if (scope->time_from_timescale()) dly_used_timescale = true;
|
||||||
|
else dly_used_no_timescale = true;
|
||||||
|
|
||||||
|
if (display_ts_dly_warning &&
|
||||||
|
dly_used_no_timescale && dly_used_timescale) {
|
||||||
|
cerr << "warning: Found both default and "
|
||||||
|
"`timescale based delays. Use" << endl;
|
||||||
|
cerr << " -Wtimescale to find the "
|
||||||
|
"module(s) with no `timescale." << endl;
|
||||||
|
display_ts_dly_warning = false;
|
||||||
|
}
|
||||||
int shift = scope->time_unit() - des->get_precision();
|
int shift = scope->time_unit() - des->get_precision();
|
||||||
|
|
||||||
/* Elaborate the delay values themselves. Remember to scale
|
/* Elaborate the delay values themselves. Remember to scale
|
||||||
|
|
@ -4289,6 +4368,7 @@ Design* elaborate(list<perm_string>roots)
|
||||||
scope->set_line(rmod);
|
scope->set_line(rmod);
|
||||||
scope->time_unit(rmod->time_unit);
|
scope->time_unit(rmod->time_unit);
|
||||||
scope->time_precision(rmod->time_precision);
|
scope->time_precision(rmod->time_precision);
|
||||||
|
scope->time_from_timescale(rmod->time_from_timescale);
|
||||||
scope->default_nettype(rmod->default_nettype);
|
scope->default_nettype(rmod->default_nettype);
|
||||||
des->set_precision(rmod->time_precision);
|
des->set_precision(rmod->time_precision);
|
||||||
|
|
||||||
|
|
@ -4369,6 +4449,7 @@ Design* elaborate(list<perm_string>roots)
|
||||||
NetScope *scope = root_elems[i]->scope;
|
NetScope *scope = root_elems[i]->scope;
|
||||||
|
|
||||||
rc &= rmod->elaborate(des, scope);
|
rc &= rmod->elaborate(des, scope);
|
||||||
|
delete root_elems[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rc == false) {
|
if (rc == false) {
|
||||||
|
|
|
||||||
12
eval_tree.cc
12
eval_tree.cc
|
|
@ -133,7 +133,7 @@ NetExpr* NetEBAdd::eval_tree(int prune_to_width)
|
||||||
|
|
||||||
if (debug_eval_tree) {
|
if (debug_eval_tree) {
|
||||||
cerr << get_fileline() << ": debug: "
|
cerr << get_fileline() << ": debug: "
|
||||||
<< "Partially evalutate " << *this
|
<< "Partially evaluate " << *this
|
||||||
<< " using (a+2)-1 --> (a+1) transform." << endl;
|
<< " using (a+2)-1 --> (a+1) transform." << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1161,16 +1161,6 @@ NetEConst* NetEConcat::eval_tree(int prune_to_width)
|
||||||
|
|
||||||
if (local_errors > 0) return 0;
|
if (local_errors > 0) return 0;
|
||||||
|
|
||||||
// Handle the special case that the repeat expression is
|
|
||||||
// zero. In this case, just return a 0 value with the expected
|
|
||||||
// width.
|
|
||||||
if (repeat_val == 0) {
|
|
||||||
verinum val (verinum::V0, expr_width());
|
|
||||||
NetEConst*res = new NetEConst(val);
|
|
||||||
res->set_width(val.len());
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
// At this point, the "gap" is the width of a single repeat of
|
// At this point, the "gap" is the width of a single repeat of
|
||||||
// the concatenation. The total width of the result is the gap
|
// the concatenation. The total width of the result is the gap
|
||||||
// times the repeat count.
|
// times the repeat count.
|
||||||
|
|
|
||||||
|
|
@ -122,6 +122,7 @@ NetNet* NetEBAdd::synthesize(Design*des, NetScope*scope, NetExpr*root)
|
||||||
NetNet*osig = new NetNet(lsig->scope(), path, NetNet::IMPLICIT, width);
|
NetNet*osig = new NetNet(lsig->scope(), path, NetNet::IMPLICIT, width);
|
||||||
osig->local_flag(true);
|
osig->local_flag(true);
|
||||||
osig->data_type(expr_type());
|
osig->data_type(expr_type());
|
||||||
|
osig->set_signed(has_sign());
|
||||||
|
|
||||||
perm_string oname = osig->scope()->local_symbol();
|
perm_string oname = osig->scope()->local_symbol();
|
||||||
NetAddSub *adder = new NetAddSub(lsig->scope(), oname, width);
|
NetAddSub *adder = new NetAddSub(lsig->scope(), oname, width);
|
||||||
|
|
@ -390,6 +391,7 @@ NetNet* NetEBPow::synthesize(Design*des, NetScope*scope, NetExpr*root)
|
||||||
NetNet::IMPLICIT, width);
|
NetNet::IMPLICIT, width);
|
||||||
osig->set_line(*this);
|
osig->set_line(*this);
|
||||||
osig->data_type(expr_type());
|
osig->data_type(expr_type());
|
||||||
|
osig->set_signed(has_sign());
|
||||||
osig->local_flag(true);
|
osig->local_flag(true);
|
||||||
|
|
||||||
connect(powr->pin_Result(), osig->pin(0));
|
connect(powr->pin_Result(), osig->pin(0));
|
||||||
|
|
@ -426,6 +428,7 @@ NetNet* NetEBMult::synthesize(Design*des, NetScope*scope, NetExpr*root)
|
||||||
NetNet::IMPLICIT, width);
|
NetNet::IMPLICIT, width);
|
||||||
osig->set_line(*this);
|
osig->set_line(*this);
|
||||||
osig->data_type(expr_type());
|
osig->data_type(expr_type());
|
||||||
|
osig->set_signed(has_sign());
|
||||||
osig->local_flag(true);
|
osig->local_flag(true);
|
||||||
|
|
||||||
connect(mult->pin_Result(), osig->pin(0));
|
connect(mult->pin_Result(), osig->pin(0));
|
||||||
|
|
@ -601,8 +604,8 @@ NetNet* NetEBShift::synthesize(Design*des, NetScope*scope, NetExpr*root)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool right_flag = op_ == 'r' || op_ == 'R';
|
const bool right_flag = op_ == 'r' || op_ == 'R';
|
||||||
const bool signed_flag = op_ == 'R';
|
const bool signed_flag = has_sign() && op_ == 'R';
|
||||||
|
|
||||||
/* Detect the special case where the shift amount is
|
/* Detect the special case where the shift amount is
|
||||||
constant. Evaluate the shift amount, and simply reconnect
|
constant. Evaluate the shift amount, and simply reconnect
|
||||||
|
|
@ -719,28 +722,42 @@ NetNet* NetEBShift::synthesize(Design*des, NetScope*scope, NetExpr*root)
|
||||||
NetNet* NetEConcat::synthesize(Design*des, NetScope*scope, NetExpr*root)
|
NetNet* NetEConcat::synthesize(Design*des, NetScope*scope, NetExpr*root)
|
||||||
{
|
{
|
||||||
/* First, synthesize the operands. */
|
/* First, synthesize the operands. */
|
||||||
|
unsigned nparms = parms_.count();
|
||||||
NetNet**tmp = new NetNet*[parms_.count()];
|
NetNet**tmp = new NetNet*[parms_.count()];
|
||||||
bool flag = true;
|
bool flag = true;
|
||||||
|
ivl_variable_type_t data_type = IVL_VT_NO_TYPE;
|
||||||
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
|
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
|
||||||
tmp[idx] = parms_[idx]->synthesize(des, scope, root);
|
if (parms_[idx]->expr_width() == 0) {
|
||||||
if (tmp[idx] == 0)
|
/* We need to synthesize a replication of zero. */
|
||||||
flag = false;
|
tmp[idx] = parms_[idx]->synthesize(des, scope, root);
|
||||||
|
assert(tmp[idx] == 0);
|
||||||
|
nparms -= 1;
|
||||||
|
} else {
|
||||||
|
tmp[idx] = parms_[idx]->synthesize(des, scope, root);
|
||||||
|
if (tmp[idx] == 0) flag = false;
|
||||||
|
/* Set the data type to the first one found. */
|
||||||
|
if (data_type == IVL_VT_NO_TYPE) {
|
||||||
|
data_type = tmp[idx]->data_type();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flag == false)
|
if (flag == false) return 0;
|
||||||
return 0;
|
|
||||||
|
|
||||||
ivl_assert(*this, tmp[0]);
|
ivl_assert(*this, data_type != IVL_VT_NO_TYPE);
|
||||||
|
|
||||||
|
/* If this is a replication of zero just return 0. */
|
||||||
|
if (expr_width() == 0) return 0;
|
||||||
|
|
||||||
/* Make a NetNet object to carry the output vector. */
|
/* Make a NetNet object to carry the output vector. */
|
||||||
perm_string path = scope->local_symbol();
|
perm_string path = scope->local_symbol();
|
||||||
NetNet*osig = new NetNet(scope, path, NetNet::IMPLICIT, expr_width());
|
NetNet*osig = new NetNet(scope, path, NetNet::IMPLICIT, expr_width());
|
||||||
osig->local_flag(true);
|
osig->local_flag(true);
|
||||||
osig->data_type(tmp[0]->data_type());
|
osig->data_type(data_type);
|
||||||
|
|
||||||
NetConcat*concat = new NetConcat(scope, scope->local_symbol(),
|
NetConcat*concat = new NetConcat(scope, scope->local_symbol(),
|
||||||
osig->vector_width(),
|
osig->vector_width(),
|
||||||
parms_.count() * repeat());
|
nparms * repeat());
|
||||||
concat->set_line(*this);
|
concat->set_line(*this);
|
||||||
des->add_node(concat);
|
des->add_node(concat);
|
||||||
connect(concat->pin(0), osig->pin(0));
|
connect(concat->pin(0), osig->pin(0));
|
||||||
|
|
@ -750,7 +767,7 @@ NetNet* NetEConcat::synthesize(Design*des, NetScope*scope, NetExpr*root)
|
||||||
for (unsigned rpt = 0; rpt < repeat(); rpt += 1) {
|
for (unsigned rpt = 0; rpt < repeat(); rpt += 1) {
|
||||||
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
|
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
|
||||||
unsigned concat_item = parms_.count()-idx-1;
|
unsigned concat_item = parms_.count()-idx-1;
|
||||||
ivl_assert(*this, tmp[concat_item]);
|
if (tmp[concat_item] == 0) continue;
|
||||||
connect(concat->pin(cur_pin), tmp[concat_item]->pin(0));
|
connect(concat->pin(cur_pin), tmp[concat_item]->pin(0));
|
||||||
cur_pin += 1;
|
cur_pin += 1;
|
||||||
count_input_width += tmp[concat_item]->vector_width();
|
count_input_width += tmp[concat_item]->vector_width();
|
||||||
|
|
@ -773,6 +790,11 @@ NetNet* NetEConst::synthesize(Design*des, NetScope*scope, NetExpr*)
|
||||||
{
|
{
|
||||||
perm_string path = scope->local_symbol();
|
perm_string path = scope->local_symbol();
|
||||||
unsigned width=expr_width();
|
unsigned width=expr_width();
|
||||||
|
if (width == 0) {
|
||||||
|
cerr << get_fileline() << ": internal error: "
|
||||||
|
<< "Found a zero width constant!" << endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
NetNet*osig = new NetNet(scope, path, NetNet::IMPLICIT, width);
|
NetNet*osig = new NetNet(scope, path, NetNet::IMPLICIT, width);
|
||||||
osig->local_flag(true);
|
osig->local_flag(true);
|
||||||
|
|
@ -1347,6 +1369,10 @@ NetNet* NetEUFunc::synthesize(Design*des, NetScope*scope, NetExpr*root)
|
||||||
/* Synthesize the arguments. */
|
/* Synthesize the arguments. */
|
||||||
bool errors = false;
|
bool errors = false;
|
||||||
for (unsigned idx = 0; idx < eparms.count(); idx += 1) {
|
for (unsigned idx = 0; idx < eparms.count(); idx += 1) {
|
||||||
|
if (dynamic_cast<NetEEvent*> (parms_[idx])) {
|
||||||
|
errors = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
NetNet*tmp = parms_[idx]->synthesize(des, scope, root);
|
NetNet*tmp = parms_[idx]->synthesize(des, scope, root);
|
||||||
if (tmp == 0) {
|
if (tmp == 0) {
|
||||||
cerr << get_fileline() << ": error: Unable to synthesize "
|
cerr << get_fileline() << ": error: Unable to synthesize "
|
||||||
|
|
|
||||||
|
|
@ -499,65 +499,3 @@ already seems to exist amongst VCD viewers in the wild, this behavior
|
||||||
seems to be acceptable according to the standard, is a better mirror
|
seems to be acceptable according to the standard, is a better mirror
|
||||||
of 4-value behavior in the dead zone, and appears more user friendly
|
of 4-value behavior in the dead zone, and appears more user friendly
|
||||||
when viewed by reasonable viewers.
|
when viewed by reasonable viewers.
|
||||||
|
|
||||||
|
|
||||||
$Id: ieee1364-notes.txt,v 1.19 2007/04/18 02:36:13 steve Exp $
|
|
||||||
$Log: ieee1364-notes.txt,v $
|
|
||||||
Revision 1.19 2007/04/18 02:36:13 steve
|
|
||||||
Put to iverilog wiki for further notes.
|
|
||||||
|
|
||||||
Revision 1.18 2007/03/22 16:08:16 steve
|
|
||||||
Spelling fixes from Larry
|
|
||||||
|
|
||||||
Revision 1.17 2003/07/15 03:49:22 steve
|
|
||||||
Spelling fixes.
|
|
||||||
|
|
||||||
Revision 1.16 2003/04/14 03:40:21 steve
|
|
||||||
Make some effort to preserve bits while
|
|
||||||
operating on constant values.
|
|
||||||
|
|
||||||
Revision 1.15 2003/02/16 23:39:08 steve
|
|
||||||
NaN in dead zones of VCD dumps.
|
|
||||||
|
|
||||||
Revision 1.14 2003/02/06 17:51:36 steve
|
|
||||||
Edge of vectors notes.
|
|
||||||
|
|
||||||
Revision 1.13 2002/08/20 04:11:53 steve
|
|
||||||
Support parameters with defined ranges.
|
|
||||||
|
|
||||||
Revision 1.12 2002/06/11 03:34:33 steve
|
|
||||||
Spelling patch (Larry Doolittle)
|
|
||||||
|
|
||||||
Revision 1.11 2002/04/27 02:38:04 steve
|
|
||||||
Support selecting bits from parameters.
|
|
||||||
|
|
||||||
Revision 1.10 2002/03/31 01:54:13 steve
|
|
||||||
Notes about scheduling
|
|
||||||
|
|
||||||
Revision 1.9 2002/01/26 02:08:07 steve
|
|
||||||
Handle x in l-value of set/x
|
|
||||||
|
|
||||||
Revision 1.8 2001/08/01 05:17:31 steve
|
|
||||||
Accept empty port lists to module instantiation.
|
|
||||||
|
|
||||||
Revision 1.7 2001/02/17 05:27:31 steve
|
|
||||||
I allow function ports to have types.
|
|
||||||
|
|
||||||
Revision 1.6 2001/02/12 16:48:04 steve
|
|
||||||
Rant about bit widths.
|
|
||||||
|
|
||||||
Revision 1.5 2001/01/02 17:28:08 steve
|
|
||||||
Resolve repeat ambiguity in favor of loop.
|
|
||||||
|
|
||||||
Revision 1.4 2001/01/01 19:12:35 steve
|
|
||||||
repeat loops ambiguity.
|
|
||||||
|
|
||||||
Revision 1.3 2000/12/15 00:21:46 steve
|
|
||||||
rounding of time and x in primitives.
|
|
||||||
|
|
||||||
Revision 1.2 2000/11/19 22:03:04 steve
|
|
||||||
Integer parameter comments.
|
|
||||||
|
|
||||||
Revision 1.1 2000/07/23 18:06:31 steve
|
|
||||||
Document ieee1364 issues.
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ iverilog-vpi - Compile front end for VPI modules
|
||||||
|
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.B iverilog-vpi
|
.B iverilog-vpi
|
||||||
[--name=\fIname\fP]
|
[\-\-name=\fIname\fP]
|
||||||
\fIsourcefile\fP...
|
\fIsourcefile\fP...
|
||||||
|
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
|
|
@ -20,7 +20,6 @@ first source file is named \fIfoo.c\fP, the output becomes
|
||||||
\fIfoo.vpi\fP.
|
\fIfoo.vpi\fP.
|
||||||
|
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
.l
|
|
||||||
\fIiverilog-vpi\fP accepts the following options:
|
\fIiverilog-vpi\fP accepts the following options:
|
||||||
.TP 8
|
.TP 8
|
||||||
.B -l\fIlibrary\fP
|
.B -l\fIlibrary\fP
|
||||||
|
|
@ -104,9 +103,9 @@ requests a 32bit vpi binary instead of the default 64bit binary.
|
||||||
.P
|
.P
|
||||||
Example GNU makefile that takes advantage of these flags:
|
Example GNU makefile that takes advantage of these flags:
|
||||||
.IP "" 4
|
.IP "" 4
|
||||||
CFLAGS = -Wall -O $(CFLAGS_$@)
|
CFLAGS = \-Wall \-O $(CFLAGS_$@)
|
||||||
.br
|
.br
|
||||||
VPI_CFLAGS := $(shell iverilog-vpi --cflags)
|
VPI_CFLAGS := $(shell iverilog-vpi \-\-cflags)
|
||||||
.br
|
.br
|
||||||
CFLAGS_messagev.o = $(VPI_CFLAGS)
|
CFLAGS_messagev.o = $(VPI_CFLAGS)
|
||||||
.br
|
.br
|
||||||
|
|
|
||||||
1
ivl.def
1
ivl.def
|
|
@ -161,6 +161,7 @@ ivl_scope_event
|
||||||
ivl_scope_events
|
ivl_scope_events
|
||||||
ivl_scope_file
|
ivl_scope_file
|
||||||
ivl_scope_is_auto
|
ivl_scope_is_auto
|
||||||
|
ivl_scope_is_cell
|
||||||
ivl_scope_lineno
|
ivl_scope_lineno
|
||||||
ivl_scope_logs
|
ivl_scope_logs
|
||||||
ivl_scope_log
|
ivl_scope_log
|
||||||
|
|
|
||||||
|
|
@ -1537,6 +1537,9 @@ extern unsigned ivl_parameter_lineno(ivl_parameter_t net);
|
||||||
* ivl_scope_is_auto
|
* ivl_scope_is_auto
|
||||||
* Is the task or function declared to be automatic?
|
* Is the task or function declared to be automatic?
|
||||||
*
|
*
|
||||||
|
* ivl_scope_is_cell
|
||||||
|
* Is the module defined to be a cell?
|
||||||
|
*
|
||||||
* ivl_scope_var
|
* ivl_scope_var
|
||||||
* ivl_scope_vars
|
* ivl_scope_vars
|
||||||
* REMOVED
|
* REMOVED
|
||||||
|
|
@ -1614,6 +1617,7 @@ extern unsigned ivl_scope_events(ivl_scope_t net);
|
||||||
extern ivl_event_t ivl_scope_event(ivl_scope_t net, unsigned idx);
|
extern ivl_event_t ivl_scope_event(ivl_scope_t net, unsigned idx);
|
||||||
extern const char* ivl_scope_file(ivl_scope_t net);
|
extern const char* ivl_scope_file(ivl_scope_t net);
|
||||||
extern unsigned ivl_scope_is_auto(ivl_scope_t net);
|
extern unsigned ivl_scope_is_auto(ivl_scope_t net);
|
||||||
|
extern unsigned ivl_scope_is_cell(ivl_scope_t net);
|
||||||
extern unsigned ivl_scope_lineno(ivl_scope_t net);
|
extern unsigned ivl_scope_lineno(ivl_scope_t net);
|
||||||
extern unsigned ivl_scope_logs(ivl_scope_t net);
|
extern unsigned ivl_scope_logs(ivl_scope_t net);
|
||||||
extern ivl_net_logic_t ivl_scope_log(ivl_scope_t net, unsigned idx);
|
extern ivl_net_logic_t ivl_scope_log(ivl_scope_t net, unsigned idx);
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@
|
||||||
Icarus Verilog LOADABLE TARGET API (ivl_target)
|
Icarus Verilog LOADABLE TARGET API (ivl_target)
|
||||||
|
|
||||||
Copyright 2002 Stephen Williams <steve@icarus.com>
|
Copyright 2002 Stephen Williams <steve@icarus.com>
|
||||||
$Id: ivl_target.txt,v 1.3 2002/06/11 03:34:33 steve Exp $
|
|
||||||
|
|
||||||
|
|
||||||
The ivl_target API is the interface available to modules that the
|
The ivl_target API is the interface available to modules that the
|
||||||
|
|
@ -38,14 +37,3 @@ other LPM device with outputs.
|
||||||
|
|
||||||
There are ivl_lpm_size() input ports, each with the width
|
There are ivl_lpm_size() input ports, each with the width
|
||||||
ivl_lpm_data2_width(). The actual nexus is indexed by ivl_lpm_data2().
|
ivl_lpm_data2_width(). The actual nexus is indexed by ivl_lpm_data2().
|
||||||
|
|
||||||
$Log: ivl_target.txt,v $
|
|
||||||
Revision 1.3 2002/06/11 03:34:33 steve
|
|
||||||
Spelling patch (Larry Doolittle)
|
|
||||||
|
|
||||||
Revision 1.2 2002/03/17 19:31:17 steve
|
|
||||||
Add API to support user defined function.
|
|
||||||
|
|
||||||
Revision 1.1 2002/03/09 02:10:22 steve
|
|
||||||
Add the NetUserFunc netlist node.
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -64,13 +64,8 @@ struct include_stack_t
|
||||||
/* If we are reparsing a macro expansion, file is 0 and this
|
/* If we are reparsing a macro expansion, file is 0 and this
|
||||||
* member points to the string in progress
|
* member points to the string in progress
|
||||||
*/
|
*/
|
||||||
const char* str;
|
char* str;
|
||||||
|
char* orig_str;
|
||||||
/* If we are reparsing a macro expansion, this member indicates
|
|
||||||
* the amount of space it occupies in the macro expansion buffer.
|
|
||||||
* This will be zero for macros without arguments.
|
|
||||||
*/
|
|
||||||
int ebs;
|
|
||||||
|
|
||||||
int stringify_flag;
|
int stringify_flag;
|
||||||
|
|
||||||
|
|
@ -462,7 +457,7 @@ keywords (include|define|undef|ifdef|ifndef|else|elseif|endif)
|
||||||
<IFCCOMMENT>\n\r |
|
<IFCCOMMENT>\n\r |
|
||||||
<IFCCOMMENT>\r\n |
|
<IFCCOMMENT>\r\n |
|
||||||
<IFCCOMMENT>\n |
|
<IFCCOMMENT>\n |
|
||||||
<IFCCOMMENT>\r { istack->lineno += 1; }
|
<IFCCOMMENT>\r { istack->lineno += 1; fputc('\n', yyout); }
|
||||||
<IFCCOMMENT>"*/" { BEGIN(comment_enter); }
|
<IFCCOMMENT>"*/" { BEGIN(comment_enter); }
|
||||||
|
|
||||||
<IFDEF_FALSE,IFDEF_SUPR>[^\r\n] { }
|
<IFDEF_FALSE,IFDEF_SUPR>[^\r\n] { }
|
||||||
|
|
@ -599,7 +594,8 @@ keywords (include|define|undef|ifdef|ifndef|else|elseif|endif)
|
||||||
|
|
||||||
<MA_ADD>"(" { macro_add_to_arg(0); ma_parenthesis_level++; }
|
<MA_ADD>"(" { macro_add_to_arg(0); ma_parenthesis_level++; }
|
||||||
|
|
||||||
<MA_ADD>"," { macro_finish_arg(); }
|
<MA_ADD>"," { if (ma_parenthesis_level > 0) macro_add_to_arg(0);
|
||||||
|
else macro_finish_arg(); }
|
||||||
|
|
||||||
<MA_ADD>")" {
|
<MA_ADD>")" {
|
||||||
if (ma_parenthesis_level > 0) {
|
if (ma_parenthesis_level > 0) {
|
||||||
|
|
@ -1352,10 +1348,17 @@ static void do_expand(int use_args)
|
||||||
struct include_stack_t*isp;
|
struct include_stack_t*isp;
|
||||||
int head = 0;
|
int head = 0;
|
||||||
int tail = 0;
|
int tail = 0;
|
||||||
|
const char *cp;
|
||||||
|
unsigned escapes = 0;
|
||||||
|
char *str_buf = 0;
|
||||||
|
|
||||||
if (cur_macro->keyword)
|
if (cur_macro->keyword)
|
||||||
{
|
{
|
||||||
fprintf(yyout, "%s", cur_macro->value);
|
fprintf(yyout, "%s", cur_macro->value);
|
||||||
|
if (do_expand_stringify_flag) {
|
||||||
|
do_expand_stringify_flag = 0;
|
||||||
|
fputc('"', yyout);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1364,6 +1367,7 @@ static void do_expand(int use_args)
|
||||||
head = exp_buf_size - exp_buf_free;
|
head = exp_buf_size - exp_buf_free;
|
||||||
expand_using_args();
|
expand_using_args();
|
||||||
tail = exp_buf_size - exp_buf_free;
|
tail = exp_buf_size - exp_buf_free;
|
||||||
|
exp_buf_free += tail - head;
|
||||||
|
|
||||||
if (tail == head)
|
if (tail == head)
|
||||||
return;
|
return;
|
||||||
|
|
@ -1376,14 +1380,47 @@ static void do_expand(int use_args)
|
||||||
if (use_args)
|
if (use_args)
|
||||||
{
|
{
|
||||||
isp->str = &exp_buf[head];
|
isp->str = &exp_buf[head];
|
||||||
isp->ebs = tail - head;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
isp->str = cur_macro->value;
|
isp->str = cur_macro->value;
|
||||||
isp->ebs = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Escape some characters if we are making a string version. */
|
||||||
|
for (cp = isp->str; (cp = strpbrk(cp, "\"\\")); cp += 1, escapes += 1);
|
||||||
|
if (escapes && isp->stringify_flag) {
|
||||||
|
unsigned idx = 0;
|
||||||
|
str_buf = (char *) malloc(strlen(isp->str)+3*escapes+1);
|
||||||
|
for (cp = isp->str; *cp; cp += 1) {
|
||||||
|
if (*cp == '"') {
|
||||||
|
str_buf[idx] = '\\';
|
||||||
|
str_buf[idx+1] = '0';
|
||||||
|
str_buf[idx+2] = '4';
|
||||||
|
str_buf[idx+3] = '2';
|
||||||
|
idx += 4;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (*cp == '\\') {
|
||||||
|
str_buf[idx] = '\\';
|
||||||
|
str_buf[idx+1] = '1';
|
||||||
|
str_buf[idx+2] = '3';
|
||||||
|
str_buf[idx+3] = '4';
|
||||||
|
idx += 4;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
str_buf[idx] = *cp;
|
||||||
|
idx += 1;
|
||||||
|
}
|
||||||
|
str_buf[idx] = 0;
|
||||||
|
idx += 1;
|
||||||
|
|
||||||
|
exp_buf_free -= idx;
|
||||||
|
|
||||||
|
isp->str = str_buf;
|
||||||
|
} else
|
||||||
|
isp->str = strdup(isp->str);
|
||||||
|
|
||||||
|
isp->orig_str = isp->str;
|
||||||
isp->next = istack;
|
isp->next = istack;
|
||||||
istack->yybs = YY_CURRENT_BUFFER;
|
istack->yybs = YY_CURRENT_BUFFER;
|
||||||
istack = isp;
|
istack = isp;
|
||||||
|
|
@ -1572,7 +1609,7 @@ static int load_next_input()
|
||||||
else
|
else
|
||||||
line_mask_flag = 1;
|
line_mask_flag = 1;
|
||||||
|
|
||||||
exp_buf_free += isp->ebs;
|
free(isp->orig_str);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isp->stringify_flag) {
|
if (isp->stringify_flag) {
|
||||||
|
|
@ -1749,7 +1786,6 @@ void reset_lexor(FILE* out, char* paths[])
|
||||||
isp->path = strdup(paths[0]);
|
isp->path = strdup(paths[0]);
|
||||||
isp->file = fopen(paths[0], "r");
|
isp->file = fopen(paths[0], "r");
|
||||||
isp->str = 0;
|
isp->str = 0;
|
||||||
isp->ebs = 0;
|
|
||||||
isp->lineno = 0;
|
isp->lineno = 0;
|
||||||
isp->stringify_flag = 0;
|
isp->stringify_flag = 0;
|
||||||
isp->comment = NULL;
|
isp->comment = NULL;
|
||||||
|
|
@ -1779,7 +1815,6 @@ void reset_lexor(FILE* out, char* paths[])
|
||||||
isp->path = strdup(paths[idx]);
|
isp->path = strdup(paths[idx]);
|
||||||
isp->file = 0;
|
isp->file = 0;
|
||||||
isp->str = 0;
|
isp->str = 0;
|
||||||
isp->ebs = 0;
|
|
||||||
isp->next = 0;
|
isp->next = 0;
|
||||||
isp->lineno = 0;
|
isp->lineno = 0;
|
||||||
isp->stringify_flag = 0;
|
isp->stringify_flag = 0;
|
||||||
|
|
@ -1807,4 +1842,5 @@ void destroy_lexor()
|
||||||
# endif
|
# endif
|
||||||
# endif
|
# endif
|
||||||
free(def_buf);
|
free(def_buf);
|
||||||
|
free(exp_buf);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
32
ivlpp/main.c
32
ivlpp/main.c
|
|
@ -214,26 +214,34 @@ int main(int argc, char*argv[])
|
||||||
FILE*precomp_out = NULL;
|
FILE*precomp_out = NULL;
|
||||||
|
|
||||||
/* Define preprocessor keywords that I plan to just pass. */
|
/* Define preprocessor keywords that I plan to just pass. */
|
||||||
|
/* From 1364-2005 Chapter 19. */
|
||||||
|
define_macro("begin_keywords", "`begin_keywords", 1, 0);
|
||||||
define_macro("celldefine", "`celldefine", 1, 0);
|
define_macro("celldefine", "`celldefine", 1, 0);
|
||||||
define_macro("default_decay_time", "`default_decay_time", 1, 0);
|
|
||||||
define_macro("default_nettype", "`default_nettype", 1, 0);
|
define_macro("default_nettype", "`default_nettype", 1, 0);
|
||||||
define_macro("default_trireg_strength", "`default_trireg_strength", 1, 0);
|
define_macro("end_keywords", "`end_keywords", 1, 0);
|
||||||
define_macro("delay_mode_distributed", "`delay_mode_distributed", 1, 0);
|
|
||||||
define_macro("delay_mode_unit", "`delay_mode_unit", 1, 0);
|
|
||||||
define_macro("delay_mode_path", "`delay_mode_path", 1, 0);
|
|
||||||
define_macro("delay_mode_zero", "`delay_mode_zero", 1, 0);
|
|
||||||
define_macro("disable_portfaults", "`disable_portfaults", 1, 0);
|
|
||||||
define_macro("enable_portfaults", "`enable_portfaults", 1, 0);
|
|
||||||
define_macro("endcelldefine", "`endcelldefine", 1, 0);
|
define_macro("endcelldefine", "`endcelldefine", 1, 0);
|
||||||
define_macro("endprotect", "`endprotect", 1, 0);
|
|
||||||
define_macro("line", "`line", 1, 0);
|
define_macro("line", "`line", 1, 0);
|
||||||
define_macro("nosuppress_faults", "`nosuppress_faults", 1, 0);
|
|
||||||
define_macro("nounconnected_drive", "`nounconnected_drive", 1, 0);
|
define_macro("nounconnected_drive", "`nounconnected_drive", 1, 0);
|
||||||
define_macro("protect", "`protect", 1, 0);
|
define_macro("pragma", "`pragma", 1, 0);
|
||||||
define_macro("resetall", "`resetall", 1, 0);
|
define_macro("resetall", "`resetall", 1, 0);
|
||||||
define_macro("suppress_faults", "`suppress_faults", 1, 0);
|
|
||||||
define_macro("timescale", "`timescale", 1, 0);
|
define_macro("timescale", "`timescale", 1, 0);
|
||||||
define_macro("unconnected_drive", "`unconnected_drive", 1, 0);
|
define_macro("unconnected_drive", "`unconnected_drive", 1, 0);
|
||||||
|
|
||||||
|
/* From 1364-2005 Annex D. */
|
||||||
|
define_macro("default_decay_time", "`default_decay_time", 1, 0);
|
||||||
|
define_macro("default_trireg_strength", "`default_trireg_strength", 1, 0);
|
||||||
|
define_macro("delay_mode_distributed", "`delay_mode_distributed", 1, 0);
|
||||||
|
define_macro("delay_mode_path", "`delay_mode_path", 1, 0);
|
||||||
|
define_macro("delay_mode_unit", "`delay_mode_unit", 1, 0);
|
||||||
|
define_macro("delay_mode_zero", "`delay_mode_zero", 1, 0);
|
||||||
|
|
||||||
|
/* From other places. */
|
||||||
|
define_macro("disable_portfaults", "`disable_portfaults", 1, 0);
|
||||||
|
define_macro("enable_portfaults", "`enable_portfaults", 1, 0);
|
||||||
|
define_macro("endprotect", "`endprotect", 1, 0);
|
||||||
|
define_macro("nosuppress_faults", "`nosuppress_faults", 1, 0);
|
||||||
|
define_macro("protect", "`protect", 1, 0);
|
||||||
|
define_macro("suppress_faults", "`suppress_faults", 1, 0);
|
||||||
define_macro("uselib", "`uselib", 1, 0);
|
define_macro("uselib", "`uselib", 1, 0);
|
||||||
|
|
||||||
include_cnt = 2;
|
include_cnt = 2;
|
||||||
|
|
|
||||||
540
lexor.lex
540
lexor.lex
|
|
@ -67,9 +67,6 @@ static const char* set_file_name(char*text)
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
extern void pform_set_timescale(int, int, const char*file, unsigned line);
|
|
||||||
|
|
||||||
void reset_lexor();
|
void reset_lexor();
|
||||||
static void line_directive();
|
static void line_directive();
|
||||||
static void line_directive2();
|
static void line_directive2();
|
||||||
|
|
@ -83,11 +80,15 @@ static verinum*make_unsized_hex(const char*txt);
|
||||||
static int dec_buf_div2(char *buf);
|
static int dec_buf_div2(char *buf);
|
||||||
|
|
||||||
static void process_timescale(const char*txt);
|
static void process_timescale(const char*txt);
|
||||||
|
static void process_ucdrive(const char*txt);
|
||||||
|
|
||||||
static list<int> keyword_mask_stack;
|
static list<int> keyword_mask_stack;
|
||||||
|
|
||||||
static int comment_enter;
|
static int comment_enter;
|
||||||
static bool in_module = false;
|
static bool in_module = false;
|
||||||
|
static bool in_UDP = false;
|
||||||
|
bool in_celldefine = false;
|
||||||
|
UCDriveType uc_drive = UCD_NONE;
|
||||||
%}
|
%}
|
||||||
|
|
||||||
%x CCOMMENT
|
%x CCOMMENT
|
||||||
|
|
@ -96,6 +97,7 @@ static bool in_module = false;
|
||||||
%x CSTRING
|
%x CSTRING
|
||||||
%s UDPTABLE
|
%s UDPTABLE
|
||||||
%x PPTIMESCALE
|
%x PPTIMESCALE
|
||||||
|
%x PPUCDRIVE
|
||||||
%x PPDEFAULT_NETTYPE
|
%x PPDEFAULT_NETTYPE
|
||||||
%x PPBEGIN_KEYWORDS
|
%x PPBEGIN_KEYWORDS
|
||||||
%s EDGES
|
%s EDGES
|
||||||
|
|
@ -107,8 +109,9 @@ S [afpnumkKMGT]
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
|
||||||
^"#line"[ ]+\"[^\"]*\"[ ]+[0-9]+.* { line_directive(); }
|
/* Recognize the various line directives. */
|
||||||
^"`line"[ ]+[0-9]+[ ]+\"[^\"]*\".* { line_directive2(); }
|
^"#line"[ \t]+.+ { line_directive(); }
|
||||||
|
^[ \t]?"`line"[ \t]+.+ { line_directive2(); }
|
||||||
|
|
||||||
[ \t\b\f\r] { ; }
|
[ \t\b\f\r] { ; }
|
||||||
\n { yylloc.first_line += 1; }
|
\n { yylloc.first_line += 1; }
|
||||||
|
|
@ -237,6 +240,14 @@ S [afpnumkKMGT]
|
||||||
in_module = false;
|
in_module = false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case K_primitive:
|
||||||
|
in_UDP = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case K_endprimitive:
|
||||||
|
in_UDP = false;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
yylval.text = 0;
|
yylval.text = 0;
|
||||||
break;
|
break;
|
||||||
|
|
@ -263,22 +274,35 @@ S [afpnumkKMGT]
|
||||||
return IDENTIFIER; }
|
return IDENTIFIER; }
|
||||||
|
|
||||||
\$([a-zA-Z0-9$_]+) {
|
\$([a-zA-Z0-9$_]+) {
|
||||||
if (strcmp(yytext,"$setuphold") == 0)
|
/* The 1364-1995 timing checks. */
|
||||||
return K_Ssetuphold;
|
|
||||||
if (strcmp(yytext,"$attribute") == 0)
|
|
||||||
return KK_attribute;
|
|
||||||
if (strcmp(yytext,"$hold") == 0)
|
if (strcmp(yytext,"$hold") == 0)
|
||||||
return K_Shold;
|
return K_Shold;
|
||||||
|
if (strcmp(yytext,"$nochange") == 0)
|
||||||
|
return K_Snochange;
|
||||||
if (strcmp(yytext,"$period") == 0)
|
if (strcmp(yytext,"$period") == 0)
|
||||||
return K_Speriod;
|
return K_Speriod;
|
||||||
if (strcmp(yytext,"$recovery") == 0)
|
if (strcmp(yytext,"$recovery") == 0)
|
||||||
return K_Srecovery;
|
return K_Srecovery;
|
||||||
if (strcmp(yytext,"$recrem") == 0)
|
|
||||||
return K_Srecrem;
|
|
||||||
if (strcmp(yytext,"$setup") == 0)
|
if (strcmp(yytext,"$setup") == 0)
|
||||||
return K_Ssetup;
|
return K_Ssetup;
|
||||||
|
if (strcmp(yytext,"$setuphold") == 0)
|
||||||
|
return K_Ssetuphold;
|
||||||
|
if (strcmp(yytext,"$skew") == 0)
|
||||||
|
return K_Sskew;
|
||||||
if (strcmp(yytext,"$width") == 0)
|
if (strcmp(yytext,"$width") == 0)
|
||||||
return K_Swidth;
|
return K_Swidth;
|
||||||
|
/* The new 1364-2001 timing checks. */
|
||||||
|
if (strcmp(yytext,"$fullskew") == 0)
|
||||||
|
return K_Sfullskew;
|
||||||
|
if (strcmp(yytext,"$recrem") == 0)
|
||||||
|
return K_Srecrem;
|
||||||
|
if (strcmp(yytext,"$removal") == 0)
|
||||||
|
return K_Sremoval;
|
||||||
|
if (strcmp(yytext,"$timeskew") == 0)
|
||||||
|
return K_Stimeskew;
|
||||||
|
|
||||||
|
if (strcmp(yytext,"$attribute") == 0)
|
||||||
|
return KK_attribute;
|
||||||
yylval.text = strdupnew(yytext);
|
yylval.text = strdupnew(yytext);
|
||||||
return SYSTEM_IDENTIFIER; }
|
return SYSTEM_IDENTIFIER; }
|
||||||
|
|
||||||
|
|
@ -348,7 +372,7 @@ S [afpnumkKMGT]
|
||||||
return REALTIME; }
|
return REALTIME; }
|
||||||
|
|
||||||
|
|
||||||
/* Notice and handle the timescale directive. */
|
/* Notice and handle the `timescale directive. */
|
||||||
|
|
||||||
^{W}?`timescale { BEGIN(PPTIMESCALE); }
|
^{W}?`timescale { BEGIN(PPTIMESCALE); }
|
||||||
<PPTIMESCALE>.* { process_timescale(yytext); }
|
<PPTIMESCALE>.* { process_timescale(yytext); }
|
||||||
|
|
@ -362,28 +386,74 @@ S [afpnumkKMGT]
|
||||||
yylloc.first_line += 1;
|
yylloc.first_line += 1;
|
||||||
BEGIN(0); }
|
BEGIN(0); }
|
||||||
|
|
||||||
|
/* Notice and handle the `celldefine and `endcelldefine directives. */
|
||||||
|
|
||||||
|
^{W}?`celldefine{W}? { in_celldefine = true; }
|
||||||
|
^{W}?`endcelldefine{W}? { in_celldefine = false; }
|
||||||
|
|
||||||
|
/* Notice and handle the resetall directive. */
|
||||||
|
|
||||||
|
^{W}?`resetall{W}? {
|
||||||
|
if (in_module) {
|
||||||
|
cerr << yylloc.text << ":" << yylloc.first_line << ": error: "
|
||||||
|
"`resetall directive can not be inside a module "
|
||||||
|
"definition." << endl;
|
||||||
|
error_count += 1;
|
||||||
|
} else if (in_UDP) {
|
||||||
|
cerr << yylloc.text << ":" << yylloc.first_line << ": error: "
|
||||||
|
"`resetall directive can not be inside a UDP "
|
||||||
|
"definition." << endl;
|
||||||
|
error_count += 1;
|
||||||
|
} else {
|
||||||
|
pform_set_default_nettype(NetNet::WIRE, yylloc.text,
|
||||||
|
yylloc.first_line);
|
||||||
|
in_celldefine = false;
|
||||||
|
uc_drive = UCD_NONE;
|
||||||
|
pform_set_timescale(def_ts_units, def_ts_prec, 0, 0);
|
||||||
|
} }
|
||||||
|
|
||||||
|
/* Notice and handle the `unconnected_drive directive. */
|
||||||
|
^{W}?`unconnected_drive { BEGIN(PPUCDRIVE); }
|
||||||
|
<PPUCDRIVE>.* { process_ucdrive(yytext); }
|
||||||
|
<PPUCDRIVE>\n {
|
||||||
|
if (in_module) {
|
||||||
|
cerr << yylloc.text << ":" << yylloc.first_line << ": error: "
|
||||||
|
"`unconnected_drive directive can not be inside a "
|
||||||
|
"module definition." << endl;
|
||||||
|
error_count += 1;
|
||||||
|
}
|
||||||
|
yylloc.first_line += 1;
|
||||||
|
BEGIN(0); }
|
||||||
|
|
||||||
|
^{W}?`nounconnected_drive{W}? {
|
||||||
|
if (in_module) {
|
||||||
|
cerr << yylloc.text << ":" << yylloc.first_line << ": error: "
|
||||||
|
"`nounconnected_drive directive can not be inside a "
|
||||||
|
"module definition." << endl;
|
||||||
|
error_count += 1;
|
||||||
|
}
|
||||||
|
uc_drive = UCD_NONE; }
|
||||||
|
|
||||||
/* These are directives that I do not yet support. I think that IVL
|
/* These are directives that I do not yet support. I think that IVL
|
||||||
should handle these, not an external preprocessor. */
|
should handle these, not an external preprocessor. */
|
||||||
|
/* From 1364-2005 Chapter 19. */
|
||||||
|
^{W}?`pragme{W}?.* { }
|
||||||
|
|
||||||
^{W}?`celldefine{W}?.* { }
|
/* From 1364-2005 Annex D. */
|
||||||
^{W}?`default_decay_time{W}?.* { }
|
^{W}?`default_decay_time{W}?.* { }
|
||||||
^{W}?`default_trireg_strength{W}?.* { }
|
^{W}?`default_trireg_strength{W}?.* { }
|
||||||
^{W}?`delay_mode_distributed{W}?.* { }
|
^{W}?`delay_mode_distributed{W}?.* { }
|
||||||
^{W}?`delay_mode_unit{W}?.* { }
|
|
||||||
^{W}?`delay_mode_path{W}?.* { }
|
^{W}?`delay_mode_path{W}?.* { }
|
||||||
|
^{W}?`delay_mode_unit{W}?.* { }
|
||||||
^{W}?`delay_mode_zero{W}?.* { }
|
^{W}?`delay_mode_zero{W}?.* { }
|
||||||
|
|
||||||
|
/* From other places. */
|
||||||
^{W}?`disable_portfaults{W}?.* { }
|
^{W}?`disable_portfaults{W}?.* { }
|
||||||
^{W}?`enable_portfaults{W}?.* { }
|
^{W}?`enable_portfaults{W}?.* { }
|
||||||
^{W}?`endcelldefine{W}?.* { }
|
|
||||||
`endprotect { }
|
`endprotect { }
|
||||||
^{W}?`line{W}?.* { }
|
|
||||||
^{W}?`nosuppress_faults{W}?.* { }
|
^{W}?`nosuppress_faults{W}?.* { }
|
||||||
^{W}?`nounconnected_drive{W}?.* { }
|
|
||||||
`protect { }
|
`protect { }
|
||||||
^{W}?`resetall{W}?.* { }
|
|
||||||
^{W}?`suppress_faults{W}?.* { }
|
^{W}?`suppress_faults{W}?.* { }
|
||||||
^{W}?`unconnected_drive{W}?.* { }
|
|
||||||
^{W}?`uselib{W}?.* { }
|
^{W}?`uselib{W}?.* { }
|
||||||
|
|
||||||
^{W}?`begin_keywords{W}? { BEGIN(PPBEGIN_KEYWORDS); }
|
^{W}?`begin_keywords{W}? { BEGIN(PPBEGIN_KEYWORDS); }
|
||||||
|
|
@ -447,16 +517,38 @@ S [afpnumkKMGT]
|
||||||
NetNet::Type net_type;
|
NetNet::Type net_type;
|
||||||
size_t wordlen = strcspn(yytext, " \t\f\r\n");
|
size_t wordlen = strcspn(yytext, " \t\f\r\n");
|
||||||
yytext[wordlen] = 0;
|
yytext[wordlen] = 0;
|
||||||
|
/* Add support for other wire types and better error detection. */
|
||||||
if (strcmp(yytext,"wire") == 0) {
|
if (strcmp(yytext,"wire") == 0) {
|
||||||
net_type = NetNet::WIRE;
|
net_type = NetNet::WIRE;
|
||||||
|
|
||||||
|
} else if (strcmp(yytext,"tri") == 0) {
|
||||||
|
net_type = NetNet::TRI;
|
||||||
|
|
||||||
|
} else if (strcmp(yytext,"tri0") == 0) {
|
||||||
|
net_type = NetNet::TRI0;
|
||||||
|
|
||||||
|
} else if (strcmp(yytext,"tri1") == 0) {
|
||||||
|
net_type = NetNet::TRI1;
|
||||||
|
|
||||||
|
} else if (strcmp(yytext,"wand") == 0) {
|
||||||
|
net_type = NetNet::WAND;
|
||||||
|
|
||||||
|
} else if (strcmp(yytext,"triand") == 0) {
|
||||||
|
net_type = NetNet::TRIAND;
|
||||||
|
|
||||||
|
} else if (strcmp(yytext,"wor") == 0) {
|
||||||
|
net_type = NetNet::WOR;
|
||||||
|
|
||||||
|
} else if (strcmp(yytext,"trior") == 0) {
|
||||||
|
net_type = NetNet::TRIOR;
|
||||||
|
|
||||||
} else if (strcmp(yytext,"none") == 0) {
|
} else if (strcmp(yytext,"none") == 0) {
|
||||||
net_type = NetNet::NONE;
|
net_type = NetNet::NONE;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
cerr << yylloc.text << ":" << yylloc.first_line
|
cerr << yylloc.text << ":" << yylloc.first_line
|
||||||
<< ": error: Net type " << yytext
|
<< ": error: Net type " << yytext
|
||||||
<< " is not a valid (and supported)"
|
<< " is not a valid (or supported)"
|
||||||
<< " default net type." << endl;
|
<< " default net type." << endl;
|
||||||
net_type = NetNet::WIRE;
|
net_type = NetNet::WIRE;
|
||||||
error_count += 1;
|
error_count += 1;
|
||||||
|
|
@ -483,6 +575,12 @@ S [afpnumkKMGT]
|
||||||
<< endl;
|
<< endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
^{W}?`elsif{W}?.* {
|
||||||
|
cerr << yylloc.text << ":" << yylloc.first_line <<
|
||||||
|
": warning: `elsif not supported. Use an external preprocessor."
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
|
||||||
^{W}?`endif{W}?.* {
|
^{W}?`endif{W}?.* {
|
||||||
cerr << yylloc.text << ":" << yylloc.first_line <<
|
cerr << yylloc.text << ":" << yylloc.first_line <<
|
||||||
": warning: `endif not supported. Use an external preprocessor."
|
": warning: `endif not supported. Use an external preprocessor."
|
||||||
|
|
@ -495,6 +593,12 @@ S [afpnumkKMGT]
|
||||||
<< endl;
|
<< endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
^{W}?`ifndef{W}?.* {
|
||||||
|
cerr << yylloc.text << ":" << yylloc.first_line <<
|
||||||
|
": warning: `ifndef not supported. Use an external preprocessor."
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
|
||||||
^`include{W}?.* {
|
^`include{W}?.* {
|
||||||
cerr << yylloc.text << ":" << yylloc.first_line <<
|
cerr << yylloc.text << ":" << yylloc.first_line <<
|
||||||
": warning: `include not supported. Use an external preprocessor."
|
": warning: `include not supported. Use an external preprocessor."
|
||||||
|
|
@ -936,6 +1040,128 @@ static verinum*make_unsized_dec(const char*ptr)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Convert the string to a time unit or precision.
|
||||||
|
* Returns true on failure.
|
||||||
|
*/
|
||||||
|
static bool get_timescale_const(const char *&cp, int &res, bool is_unit)
|
||||||
|
{
|
||||||
|
/* Check for the 1 digit. */
|
||||||
|
if (*cp != '1') {
|
||||||
|
if (is_unit) {
|
||||||
|
VLerror(yylloc, "Invalid `timescale unit constant "
|
||||||
|
"(1st digit)");
|
||||||
|
} else {
|
||||||
|
VLerror(yylloc, "Invalid `timescale precision constant "
|
||||||
|
"(1st digit)");
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
cp += 1;
|
||||||
|
|
||||||
|
/* Check the number of zeros after the 1. */
|
||||||
|
res = strspn(cp, "0");
|
||||||
|
if (res > 2) {
|
||||||
|
if (is_unit) {
|
||||||
|
VLerror(yylloc, "Invalid `timescale unit constant "
|
||||||
|
"(number of zeros)");
|
||||||
|
} else {
|
||||||
|
VLerror(yylloc, "Invalid `timescale precision constant "
|
||||||
|
"(number of zeros)");
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
cp += res;
|
||||||
|
|
||||||
|
/* Skip any space between the digits and the scaling string. */
|
||||||
|
cp += strspn(cp, " \t");
|
||||||
|
|
||||||
|
/* Now process the scaling string. */
|
||||||
|
if (strncmp("s", cp, 1) == 0) {
|
||||||
|
res -= 0;
|
||||||
|
cp += 1;
|
||||||
|
return false;
|
||||||
|
|
||||||
|
} else if (strncmp("ms", cp, 2) == 0) {
|
||||||
|
res -= 3;
|
||||||
|
cp += 2;
|
||||||
|
return false;
|
||||||
|
|
||||||
|
} else if (strncmp("us", cp, 2) == 0) {
|
||||||
|
res -= 6;
|
||||||
|
cp += 2;
|
||||||
|
return false;
|
||||||
|
|
||||||
|
} else if (strncmp("ns", cp, 2) == 0) {
|
||||||
|
res -= 9;
|
||||||
|
cp += 2;
|
||||||
|
return false;
|
||||||
|
|
||||||
|
} else if (strncmp("ps", cp, 2) == 0) {
|
||||||
|
res -= 12;
|
||||||
|
cp += 2;
|
||||||
|
return false;
|
||||||
|
|
||||||
|
} else if (strncmp("fs", cp, 2) == 0) {
|
||||||
|
res -= 15;
|
||||||
|
cp += 2;
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_unit) {
|
||||||
|
VLerror(yylloc, "Invalid `timescale unit scale");
|
||||||
|
} else {
|
||||||
|
VLerror(yylloc, "Invalid `timescale precision scale");
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* process either a pull0 or a pull1.
|
||||||
|
*/
|
||||||
|
static void process_ucdrive(const char*txt)
|
||||||
|
{
|
||||||
|
UCDriveType ucd = UCD_NONE;
|
||||||
|
const char*cp = txt + strspn(txt, " \t");
|
||||||
|
|
||||||
|
/* Skip the space after the `unconnected_drive directive. */
|
||||||
|
if (cp == txt) {
|
||||||
|
VLerror(yylloc, "Space required after `unconnected_drive "
|
||||||
|
"directive.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check for the pull keyword. */
|
||||||
|
if (strncmp("pull", cp, 4) != 0) {
|
||||||
|
VLerror(yylloc, "pull required for `unconnected_drive "
|
||||||
|
"directive.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cp += 4;
|
||||||
|
if (*cp == '0') ucd = UCD_PULL0;
|
||||||
|
else if (*cp == '1') ucd = UCD_PULL1;
|
||||||
|
else {
|
||||||
|
cerr << yylloc.text << ":" << yylloc.first_line << ": error: "
|
||||||
|
"`unconnected_drive does not support 'pull" << *cp
|
||||||
|
<< "'." << endl;
|
||||||
|
error_count += 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cp += 1;
|
||||||
|
|
||||||
|
/* Verify that only space and/or a single line comment is left. */
|
||||||
|
cp += strspn(cp, " \t");
|
||||||
|
if (strncmp(cp, "//", 2) != 0 &&
|
||||||
|
(size_t)(cp-yytext) != strlen(yytext)) {
|
||||||
|
VLerror(yylloc, "Invalid `unconnected_dirve directive (extra "
|
||||||
|
"garbage after precision).");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uc_drive = ucd;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The timescale parameter has the form:
|
* The timescale parameter has the form:
|
||||||
|
|
@ -943,98 +1169,46 @@ static verinum*make_unsized_dec(const char*ptr)
|
||||||
*/
|
*/
|
||||||
static void process_timescale(const char*txt)
|
static void process_timescale(const char*txt)
|
||||||
{
|
{
|
||||||
unsigned num;
|
|
||||||
const char*cp = txt + strspn(txt, " \t");
|
const char*cp = txt + strspn(txt, " \t");
|
||||||
char*tmp;
|
|
||||||
const char*ctmp;
|
/* Skip the space after the `timescale directive. */
|
||||||
|
if (cp == txt) {
|
||||||
|
VLerror(yylloc, "Space required after `timescale directive.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int unit = 0;
|
int unit = 0;
|
||||||
int prec = 0;
|
int prec = 0;
|
||||||
|
|
||||||
num = strtoul(cp, &tmp, 10);
|
/* Get the time units. */
|
||||||
if (num == 0) {
|
if (get_timescale_const(cp, unit, true)) return;
|
||||||
VLerror(yylloc, "Invalid timescale string.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (num >= 10) {
|
/* Skip any space after the time units, the '/' and any
|
||||||
unit += 1;
|
* space after the '/'. */
|
||||||
num /= 10;
|
|
||||||
}
|
|
||||||
if (num != 1) {
|
|
||||||
VLerror(yylloc, "Invalid timescale unit number.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
cp = tmp;
|
|
||||||
cp += strspn(cp, " \t");
|
cp += strspn(cp, " \t");
|
||||||
ctmp = cp + strcspn(cp, " \t/");
|
if (*cp != '/') {
|
||||||
|
VLerror(yylloc, "`timescale separator '/' appears to be missing.");
|
||||||
if (strncmp("s", cp, ctmp-cp) == 0) {
|
|
||||||
unit -= 0;
|
|
||||||
|
|
||||||
} else if (strncmp("ms", cp, ctmp-cp) == 0) {
|
|
||||||
unit -= 3;
|
|
||||||
|
|
||||||
} else if (strncmp("us", cp, ctmp-cp) == 0) {
|
|
||||||
unit -= 6;
|
|
||||||
|
|
||||||
} else if (strncmp("ns", cp, ctmp-cp) == 0) {
|
|
||||||
unit -= 9;
|
|
||||||
|
|
||||||
} else if (strncmp("ps", cp, ctmp-cp) == 0) {
|
|
||||||
unit -= 12;
|
|
||||||
|
|
||||||
} else if (strncmp("fs", cp, ctmp-cp) == 0) {
|
|
||||||
unit -= 15;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
VLerror(yylloc, "Invalid timescale unit of measurement");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
cp += 1;
|
||||||
cp = ctmp;
|
|
||||||
cp += strspn(cp, " \t/");
|
|
||||||
|
|
||||||
num = strtoul(cp, &tmp, 10);
|
|
||||||
if (num == 0) {
|
|
||||||
VLerror(yylloc, "Invalid timescale string.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
assert(num);
|
|
||||||
while (num >= 10) {
|
|
||||||
prec += 1;
|
|
||||||
num /= 10;
|
|
||||||
}
|
|
||||||
if (num != 1) {
|
|
||||||
VLerror(yylloc, "Invalid timescale precision number.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
cp = tmp;
|
|
||||||
cp += strspn(cp, " \t");
|
cp += strspn(cp, " \t");
|
||||||
ctmp = cp + strcspn(cp, " \t\r");
|
|
||||||
|
|
||||||
if (strncmp("s", cp, ctmp-cp) == 0) {
|
/* Get the time precision. */
|
||||||
prec -= 0;
|
if (get_timescale_const(cp, prec, false)) return;
|
||||||
|
|
||||||
} else if (strncmp("ms", cp, ctmp-cp) == 0) {
|
/* Verify that only space and/or a single line comment is left. */
|
||||||
prec -= 3;
|
cp += strspn(cp, " \t");
|
||||||
|
if (strncmp(cp, "//", 2) != 0 &&
|
||||||
|
(size_t)(cp-yytext) != strlen(yytext)) {
|
||||||
|
VLerror(yylloc, "Invalid `timescale directive (extra garbage "
|
||||||
|
"after precision).");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
} else if (strncmp("us", cp, ctmp-cp) == 0) {
|
/* The time unit must be greater than or equal to the precision. */
|
||||||
prec -= 6;
|
if (unit < prec) {
|
||||||
|
VLerror(yylloc, "error: `timescale unit must not be less than "
|
||||||
} else if (strncmp("ns", cp, ctmp-cp) == 0) {
|
"the precision.");
|
||||||
prec -= 9;
|
|
||||||
|
|
||||||
} else if (strncmp("ps", cp, ctmp-cp) == 0) {
|
|
||||||
prec -= 12;
|
|
||||||
|
|
||||||
} else if (strncmp("fs", cp, ctmp-cp) == 0) {
|
|
||||||
prec -= 15;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
VLerror(yylloc, "Invalid timescale precision units of measurement");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1053,47 +1227,149 @@ int yywrap()
|
||||||
*/
|
*/
|
||||||
static void line_directive()
|
static void line_directive()
|
||||||
{
|
{
|
||||||
char*qt1 = strchr(yytext, '"');
|
char *cpr;
|
||||||
assert(qt1);
|
/* Skip any leading space. */
|
||||||
qt1 += 1;
|
char *cp = strchr(yytext, '#');
|
||||||
|
/* Skip the #line directive. */
|
||||||
|
assert(strncmp(cp, "#line", 5) == 0);
|
||||||
|
cp += 5;
|
||||||
|
/* Skip the space after the #line directive. */
|
||||||
|
cp += strspn(cp, " \t");
|
||||||
|
|
||||||
char*qt2 = strchr(qt1, '"');
|
/* Find the starting " and skip it. */
|
||||||
assert(qt2);
|
char*fn_start = strchr(cp, '"');
|
||||||
|
if (cp != fn_start) {
|
||||||
|
VLerror(yylloc, "Invalid #line directive (file name start).");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fn_start += 1;
|
||||||
|
|
||||||
char*buf = new char[qt2-qt1+1];
|
/* Find the last ". */
|
||||||
strncpy(buf, qt1, qt2-qt1);
|
char*fn_end = strrchr(fn_start, '"');
|
||||||
buf[qt2-qt1] = 0;
|
if (!fn_end) {
|
||||||
|
VLerror(yylloc, "Invalid #line directive (file name end).");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy the file name and assign it to yylloc. */
|
||||||
|
char*buf = new char[fn_end-fn_start+1];
|
||||||
|
strncpy(buf, fn_start, fn_end-fn_start);
|
||||||
|
buf[fn_end-fn_start] = 0;
|
||||||
|
|
||||||
|
/* Skip the space after the file name. */
|
||||||
|
cp = fn_end;
|
||||||
|
cp += 1;
|
||||||
|
cpr = cp;
|
||||||
|
cpr += strspn(cp, " \t");
|
||||||
|
if (cp == cpr) {
|
||||||
|
VLerror(yylloc, "Invalid #line directive (missing space after "
|
||||||
|
"file name).");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cp = cpr;
|
||||||
|
|
||||||
|
/* Get the line number and verify that it is correct. */
|
||||||
|
unsigned long lineno = strtoul(cp, &cpr, 10);
|
||||||
|
if (cp == cpr) {
|
||||||
|
VLerror(yylloc, "Invalid line number for #line directive.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cp = cpr;
|
||||||
|
|
||||||
|
/* Verify that only space is left. */
|
||||||
|
cpr += strspn(cp, " \t");
|
||||||
|
if ((size_t)(cpr-yytext) != strlen(yytext)) {
|
||||||
|
VLerror(yylloc, "Invalid #line directive (extra garbage after "
|
||||||
|
"line number).");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now we can assign the new values to yyloc. */
|
||||||
yylloc.text = set_file_name(buf);
|
yylloc.text = set_file_name(buf);
|
||||||
|
yylloc.first_line = lineno;
|
||||||
qt2 += 1;
|
|
||||||
yylloc.first_line = strtoul(qt2,0,0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The line directive matches lines of the form `line N "foo" M and
|
||||||
|
* calls this function. Here I parse out the file name and line
|
||||||
|
* number, and change the yylloc to suite. M is ignored.
|
||||||
|
*/
|
||||||
static void line_directive2()
|
static void line_directive2()
|
||||||
{
|
{
|
||||||
assert(strncmp(yytext,"`line",5) == 0);
|
char *cpr;
|
||||||
char*cp = yytext + strlen("`line");
|
/* Skip any leading space. */
|
||||||
cp += strspn(cp, " ");
|
char *cp = strchr(yytext, '`');
|
||||||
yylloc.first_line = strtoul(cp,&cp,10);
|
/* Skip the `line directive. */
|
||||||
|
assert(strncmp(cp, "`line", 5) == 0);
|
||||||
|
cp += 5;
|
||||||
|
|
||||||
yylloc.first_line -= 1;
|
/* strtoul skips leading space. */
|
||||||
|
unsigned long lineno = strtoul(cp, &cpr, 10);
|
||||||
|
if (cp == cpr) {
|
||||||
|
VLerror(yylloc, "Invalid line number for `line directive.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
lineno -= 1;
|
||||||
|
cp = cpr;
|
||||||
|
|
||||||
cp += strspn(cp, " ");
|
/* Skip the space between the line number and the file name. */
|
||||||
if (*cp == 0) return;
|
cpr += strspn(cp, " \t");
|
||||||
|
if (cp == cpr) {
|
||||||
|
VLerror(yylloc, "Invalid `line directive (missing space after "
|
||||||
|
"line number).");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cp = cpr;
|
||||||
|
|
||||||
char*qt1 = strchr(yytext, '"');
|
/* Find the starting " and skip it. */
|
||||||
assert(qt1);
|
char*fn_start = strchr(cp, '"');
|
||||||
qt1 += 1;
|
if (cp != fn_start) {
|
||||||
|
VLerror(yylloc, "Invalid `line directive (file name start).");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fn_start += 1;
|
||||||
|
|
||||||
char*qt2 = strchr(qt1, '"');
|
/* Find the last ". */
|
||||||
assert(qt2);
|
char*fn_end = strrchr(fn_start, '"');
|
||||||
|
if (!fn_end) {
|
||||||
|
VLerror(yylloc, "Invalid `line directive (file name end).");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
char*buf = new char[qt2-qt1+1];
|
/* Skip the space after the file name. */
|
||||||
strncpy(buf, qt1, qt2-qt1);
|
cp = fn_end + 1;
|
||||||
buf[qt2-qt1] = 0;
|
cpr = cp;
|
||||||
|
cpr += strspn(cp, " \t");
|
||||||
|
if (cp == cpr) {
|
||||||
|
VLerror(yylloc, "Invalid `line directive (missing space after "
|
||||||
|
"file name).");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cp = cpr;
|
||||||
|
|
||||||
|
/* Check that the level is correct, we do not need the level. */
|
||||||
|
if (strspn(cp, "012") != 1) {
|
||||||
|
VLerror(yylloc, "Invalid level for `line directive.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cp += 1;
|
||||||
|
|
||||||
|
/* Verify that only space and/or a single line comment is left. */
|
||||||
|
cp += strspn(cp, " \t");
|
||||||
|
if (strncmp(cp, "//", 2) != 0 &&
|
||||||
|
(size_t)(cp-yytext) != strlen(yytext)) {
|
||||||
|
VLerror(yylloc, "Invalid `line directive (extra garbage after "
|
||||||
|
"level).");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy the file name and assign it and the line number to yylloc. */
|
||||||
|
char*buf = new char[fn_end-fn_start+1];
|
||||||
|
strncpy(buf, fn_start, fn_end-fn_start);
|
||||||
|
buf[fn_end-fn_start] = 0;
|
||||||
|
|
||||||
yylloc.text = set_file_name(buf);
|
yylloc.text = set_file_name(buf);
|
||||||
|
yylloc.first_line = lineno;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern FILE*vl_input;
|
extern FILE*vl_input;
|
||||||
|
|
@ -1105,3 +1381,17 @@ void reset_lexor()
|
||||||
/* Announce the first file name. */
|
/* Announce the first file name. */
|
||||||
yylloc.text = set_file_name(strdupnew(vl_file.c_str()));
|
yylloc.text = set_file_name(strdupnew(vl_file.c_str()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Modern version of flex (>=2.5.9) can clean up the scanner data.
|
||||||
|
*/
|
||||||
|
void destroy_lexor()
|
||||||
|
{
|
||||||
|
# ifdef FLEX_SCANNER
|
||||||
|
# if YY_FLEX_MAJOR_VERSION >= 2 && YY_FLEX_MINOR_VERSION >= 5
|
||||||
|
# if defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9
|
||||||
|
yylex_destroy();
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,165 +11,183 @@
|
||||||
%}
|
%}
|
||||||
struct lexor_keyword { const char*name; int mask; int tokenType; };
|
struct lexor_keyword { const char*name; int mask; int tokenType; };
|
||||||
%%
|
%%
|
||||||
abs, GN_KEYWORDS_VAMS_2_3, K_abs
|
abs, GN_KEYWORDS_VAMS_2_3, K_abs
|
||||||
abstol, GN_KEYWORDS_VAMS_2_3, K_abstol
|
abstol, GN_KEYWORDS_VAMS_2_3, K_abstol
|
||||||
access, GN_KEYWORDS_VAMS_2_3, K_access
|
access, GN_KEYWORDS_VAMS_2_3, K_access
|
||||||
acos, GN_KEYWORDS_VAMS_2_3, K_acos
|
acos, GN_KEYWORDS_VAMS_2_3, K_acos
|
||||||
acosh, GN_KEYWORDS_VAMS_2_3, K_acosh
|
acosh, GN_KEYWORDS_VAMS_2_3, K_acosh
|
||||||
always, GN_KEYWORDS_1364_1995, K_always
|
always, GN_KEYWORDS_1364_1995, K_always
|
||||||
always_comb, GN_KEYWORDS_1800_2005, K_always_comb
|
always_comb, GN_KEYWORDS_1800_2005, K_always_comb
|
||||||
always_ff, GN_KEYWORDS_1800_2005, K_always_ff
|
always_ff, GN_KEYWORDS_1800_2005, K_always_ff
|
||||||
always_latch, GN_KEYWORDS_1800_2005, K_always_latch
|
always_latch, GN_KEYWORDS_1800_2005, K_always_latch
|
||||||
analog, GN_KEYWORDS_VAMS_2_3, K_analog
|
analog, GN_KEYWORDS_VAMS_2_3, K_analog
|
||||||
and, GN_KEYWORDS_1364_1995, K_and
|
and, GN_KEYWORDS_1364_1995, K_and
|
||||||
asin, GN_KEYWORDS_VAMS_2_3, K_asin
|
asin, GN_KEYWORDS_VAMS_2_3, K_asin
|
||||||
asinh, GN_KEYWORDS_VAMS_2_3, K_asinh
|
asinh, GN_KEYWORDS_VAMS_2_3, K_asinh
|
||||||
assert, GN_KEYWORDS_1800_2005, K_assert
|
assert, GN_KEYWORDS_1800_2005, K_assert
|
||||||
assign, GN_KEYWORDS_1364_1995, K_assign
|
assign, GN_KEYWORDS_1364_1995, K_assign
|
||||||
atan, GN_KEYWORDS_VAMS_2_3, K_atan
|
atan, GN_KEYWORDS_VAMS_2_3, K_atan
|
||||||
atan2, GN_KEYWORDS_VAMS_2_3, K_atan2
|
atan2, GN_KEYWORDS_VAMS_2_3, K_atan2
|
||||||
atanh, GN_KEYWORDS_VAMS_2_3, K_atanh
|
atanh, GN_KEYWORDS_VAMS_2_3, K_atanh
|
||||||
automatic, GN_KEYWORDS_1364_2001, K_automatic
|
automatic, GN_KEYWORDS_1364_2001, K_automatic
|
||||||
begin, GN_KEYWORDS_1364_1995, K_begin
|
begin, GN_KEYWORDS_1364_1995, K_begin
|
||||||
bool, GN_KEYWORDS_ICARUS, K_bool
|
bool, GN_KEYWORDS_ICARUS, K_bool
|
||||||
buf, GN_KEYWORDS_1364_1995, K_buf
|
buf, GN_KEYWORDS_1364_1995, K_buf
|
||||||
bufif0, GN_KEYWORDS_1364_1995, K_bufif0
|
bufif0, GN_KEYWORDS_1364_1995, K_bufif0
|
||||||
bufif1, GN_KEYWORDS_1364_1995, K_bufif1
|
bufif1, GN_KEYWORDS_1364_1995, K_bufif1
|
||||||
case, GN_KEYWORDS_1364_1995, K_case
|
case, GN_KEYWORDS_1364_1995, K_case
|
||||||
casex, GN_KEYWORDS_1364_1995, K_casex
|
casex, GN_KEYWORDS_1364_1995, K_casex
|
||||||
casez, GN_KEYWORDS_1364_1995, K_casez
|
casez, GN_KEYWORDS_1364_1995, K_casez
|
||||||
ceil, GN_KEYWORDS_VAMS_2_3, K_ceil
|
ceil, GN_KEYWORDS_VAMS_2_3, K_ceil
|
||||||
cmos, GN_KEYWORDS_1364_1995, K_cmos
|
cell, GN_KEYWORDS_1364_2001_CONFIG, K_cell
|
||||||
continuous, GN_KEYWORDS_VAMS_2_3, K_continuous
|
cmos, GN_KEYWORDS_1364_1995, K_cmos
|
||||||
cos, GN_KEYWORDS_VAMS_2_3, K_cos
|
config, GN_KEYWORDS_1364_2001_CONFIG, K_config
|
||||||
cosh, GN_KEYWORDS_VAMS_2_3, K_cosh
|
continuous, GN_KEYWORDS_VAMS_2_3, K_continuous
|
||||||
ddt_nature, GN_KEYWORDS_VAMS_2_3, K_ddt_nature
|
cos, GN_KEYWORDS_VAMS_2_3, K_cos
|
||||||
deassign, GN_KEYWORDS_1364_1995, K_deassign
|
cosh, GN_KEYWORDS_VAMS_2_3, K_cosh
|
||||||
default, GN_KEYWORDS_1364_1995, K_default
|
ddt_nature, GN_KEYWORDS_VAMS_2_3, K_ddt_nature
|
||||||
defparam, GN_KEYWORDS_1364_1995, K_defparam
|
deassign, GN_KEYWORDS_1364_1995, K_deassign
|
||||||
disable, GN_KEYWORDS_1364_1995, K_disable
|
default, GN_KEYWORDS_1364_1995, K_default
|
||||||
discipline, GN_KEYWORDS_VAMS_2_3, K_discipline
|
defparam, GN_KEYWORDS_1364_1995, K_defparam
|
||||||
discrete, GN_KEYWORDS_VAMS_2_3, K_discrete
|
design, GN_KEYWORDS_1364_2001_CONFIG, K_design
|
||||||
domain, GN_KEYWORDS_VAMS_2_3, K_domain
|
disable, GN_KEYWORDS_1364_1995, K_disable
|
||||||
edge, GN_KEYWORDS_1364_1995, K_edge
|
discipline, GN_KEYWORDS_VAMS_2_3, K_discipline
|
||||||
else, GN_KEYWORDS_1364_1995, K_else
|
discrete, GN_KEYWORDS_VAMS_2_3, K_discrete
|
||||||
end, GN_KEYWORDS_1364_1995, K_end
|
domain, GN_KEYWORDS_VAMS_2_3, K_domain
|
||||||
endcase, GN_KEYWORDS_1364_1995, K_endcase
|
edge, GN_KEYWORDS_1364_1995, K_edge
|
||||||
enddiscipline, GN_KEYWORDS_VAMS_2_3, K_enddiscipline
|
else, GN_KEYWORDS_1364_1995, K_else
|
||||||
endfunction, GN_KEYWORDS_1364_1995, K_endfunction
|
end, GN_KEYWORDS_1364_1995, K_end
|
||||||
endgenerate, GN_KEYWORDS_1364_1995, K_endgenerate
|
endcase, GN_KEYWORDS_1364_1995, K_endcase
|
||||||
endmodule, GN_KEYWORDS_1364_1995, K_endmodule
|
endconfig, GN_KEYWORDS_1364_2001_CONFIG, K_endconfig
|
||||||
endnature, GN_KEYWORDS_VAMS_2_3, K_endnature
|
enddiscipline, GN_KEYWORDS_VAMS_2_3, K_enddiscipline
|
||||||
endprimitive, GN_KEYWORDS_1364_1995, K_endprimitive
|
endfunction, GN_KEYWORDS_1364_1995, K_endfunction
|
||||||
endspecify, GN_KEYWORDS_1364_1995, K_endspecify
|
endgenerate, GN_KEYWORDS_1364_2001, K_endgenerate
|
||||||
endtable, GN_KEYWORDS_1364_1995, K_endtable
|
endmodule, GN_KEYWORDS_1364_1995, K_endmodule
|
||||||
endtask, GN_KEYWORDS_1364_1995, K_endtask
|
endnature, GN_KEYWORDS_VAMS_2_3, K_endnature
|
||||||
event, GN_KEYWORDS_1364_1995, K_event
|
endprimitive, GN_KEYWORDS_1364_1995, K_endprimitive
|
||||||
exclude, GN_KEYWORDS_VAMS_2_3, K_exclude
|
endspecify, GN_KEYWORDS_1364_1995, K_endspecify
|
||||||
exp, GN_KEYWORDS_VAMS_2_3, K_exp
|
endtable, GN_KEYWORDS_1364_1995, K_endtable
|
||||||
floor, GN_KEYWORDS_VAMS_2_3, K_floor
|
endtask, GN_KEYWORDS_1364_1995, K_endtask
|
||||||
flow, GN_KEYWORDS_VAMS_2_3, K_flow
|
event, GN_KEYWORDS_1364_1995, K_event
|
||||||
for, GN_KEYWORDS_1364_1995, K_for
|
exclude, GN_KEYWORDS_VAMS_2_3, K_exclude
|
||||||
force, GN_KEYWORDS_1364_1995, K_force
|
exp, GN_KEYWORDS_VAMS_2_3, K_exp
|
||||||
forever, GN_KEYWORDS_1364_1995, K_forever
|
floor, GN_KEYWORDS_VAMS_2_3, K_floor
|
||||||
fork, GN_KEYWORDS_1364_1995, K_fork
|
flow, GN_KEYWORDS_VAMS_2_3, K_flow
|
||||||
from, GN_KEYWORDS_VAMS_2_3, K_from
|
for, GN_KEYWORDS_1364_1995, K_for
|
||||||
function, GN_KEYWORDS_1364_1995, K_function
|
force, GN_KEYWORDS_1364_1995, K_force
|
||||||
generate, GN_KEYWORDS_1364_2001, K_generate
|
forever, GN_KEYWORDS_1364_1995, K_forever
|
||||||
genvar, GN_KEYWORDS_1364_2001, K_genvar
|
fork, GN_KEYWORDS_1364_1995, K_fork
|
||||||
ground, GN_KEYWORDS_VAMS_2_3, K_ground
|
from, GN_KEYWORDS_VAMS_2_3, K_from
|
||||||
highz0, GN_KEYWORDS_1364_1995, K_highz0
|
function, GN_KEYWORDS_1364_1995, K_function
|
||||||
highz1, GN_KEYWORDS_1364_1995, K_highz1
|
generate, GN_KEYWORDS_1364_2001, K_generate
|
||||||
hypot, GN_KEYWORDS_VAMS_2_3, K_hypot
|
genvar, GN_KEYWORDS_1364_2001, K_genvar
|
||||||
idt_nature, GN_KEYWORDS_VAMS_2_3, K_idt_nature
|
ground, GN_KEYWORDS_VAMS_2_3, K_ground
|
||||||
if, GN_KEYWORDS_1364_1995, K_if
|
highz0, GN_KEYWORDS_1364_1995, K_highz0
|
||||||
ifnone, GN_KEYWORDS_1364_1995, K_ifnone
|
highz1, GN_KEYWORDS_1364_1995, K_highz1
|
||||||
inf, GN_KEYWORDS_VAMS_2_3, K_inf
|
hypot, GN_KEYWORDS_VAMS_2_3, K_hypot
|
||||||
initial, GN_KEYWORDS_1364_1995, K_initial
|
idt_nature, GN_KEYWORDS_VAMS_2_3, K_idt_nature
|
||||||
inout, GN_KEYWORDS_1364_1995, K_inout
|
if, GN_KEYWORDS_1364_1995, K_if
|
||||||
input, GN_KEYWORDS_1364_1995, K_input
|
ifnone, GN_KEYWORDS_1364_1995, K_ifnone
|
||||||
integer, GN_KEYWORDS_1364_1995, K_integer
|
incdir, GN_KEYWORDS_1364_2001_CONFIG, K_incdir
|
||||||
join, GN_KEYWORDS_1364_1995, K_join
|
include, GN_KEYWORDS_1364_2001_CONFIG, K_include
|
||||||
large, GN_KEYWORDS_1364_1995, K_large
|
inf, GN_KEYWORDS_VAMS_2_3, K_inf
|
||||||
ln, GN_KEYWORDS_VAMS_2_3, K_ln
|
initial, GN_KEYWORDS_1364_1995, K_initial
|
||||||
localparam, GN_KEYWORDS_1364_2001, K_localparam
|
inout, GN_KEYWORDS_1364_1995, K_inout
|
||||||
log, GN_KEYWORDS_VAMS_2_3, K_log
|
input, GN_KEYWORDS_1364_1995, K_input
|
||||||
logic, GN_KEYWORDS_ICARUS, K_logic
|
instance, GN_KEYWORDS_1364_2001_CONFIG, K_instance
|
||||||
macromodule, GN_KEYWORDS_1364_1995, K_macromodule
|
integer, GN_KEYWORDS_1364_1995, K_integer
|
||||||
max, GN_KEYWORDS_VAMS_2_3, K_max
|
join, GN_KEYWORDS_1364_1995, K_join
|
||||||
medium, GN_KEYWORDS_1364_1995, K_medium
|
large, GN_KEYWORDS_1364_1995, K_large
|
||||||
min, GN_KEYWORDS_VAMS_2_3, K_min
|
liblist, GN_KEYWORDS_1364_2001_CONFIG, K_liblist
|
||||||
module, GN_KEYWORDS_1364_1995, K_module
|
library, GN_KEYWORDS_1364_2001_CONFIG, K_library
|
||||||
nand, GN_KEYWORDS_1364_1995, K_nand
|
ln, GN_KEYWORDS_VAMS_2_3, K_ln
|
||||||
nature, GN_KEYWORDS_VAMS_2_3, K_nature
|
localparam, GN_KEYWORDS_1364_2001, K_localparam
|
||||||
negedge, GN_KEYWORDS_1364_1995, K_negedge
|
log, GN_KEYWORDS_VAMS_2_3, K_log
|
||||||
nmos, GN_KEYWORDS_1364_1995, K_nmos
|
logic, GN_KEYWORDS_ICARUS, K_logic
|
||||||
nor, GN_KEYWORDS_1364_1995, K_nor
|
macromodule, GN_KEYWORDS_1364_1995, K_macromodule
|
||||||
not, GN_KEYWORDS_1364_1995, K_not
|
max, GN_KEYWORDS_VAMS_2_3, K_max
|
||||||
notif0, GN_KEYWORDS_1364_1995, K_notif0
|
medium, GN_KEYWORDS_1364_1995, K_medium
|
||||||
notif1, GN_KEYWORDS_1364_1995, K_notif1
|
min, GN_KEYWORDS_VAMS_2_3, K_min
|
||||||
or, GN_KEYWORDS_1364_1995, K_or
|
module, GN_KEYWORDS_1364_1995, K_module
|
||||||
output, GN_KEYWORDS_1364_1995, K_output
|
nand, GN_KEYWORDS_1364_1995, K_nand
|
||||||
parameter, GN_KEYWORDS_1364_1995, K_parameter
|
nature, GN_KEYWORDS_VAMS_2_3, K_nature
|
||||||
pmos, GN_KEYWORDS_1364_1995, K_pmos
|
negedge, GN_KEYWORDS_1364_1995, K_negedge
|
||||||
posedge, GN_KEYWORDS_1364_1995, K_posedge
|
nmos, GN_KEYWORDS_1364_1995, K_nmos
|
||||||
potential, GN_KEYWORDS_VAMS_2_3, K_potential
|
nor, GN_KEYWORDS_1364_1995, K_nor
|
||||||
pow, GN_KEYWORDS_VAMS_2_3, K_pow
|
noshowcancelled, GN_KEYWORDS_1364_2001, K_noshowcancelled
|
||||||
primitive, GN_KEYWORDS_1364_1995, K_primitive
|
not, GN_KEYWORDS_1364_1995, K_not
|
||||||
pull0, GN_KEYWORDS_1364_1995, K_pull0
|
notif0, GN_KEYWORDS_1364_1995, K_notif0
|
||||||
pull1, GN_KEYWORDS_1364_1995, K_pull1
|
notif1, GN_KEYWORDS_1364_1995, K_notif1
|
||||||
pulldown, GN_KEYWORDS_1364_1995, K_pulldown
|
or, GN_KEYWORDS_1364_1995, K_or
|
||||||
pullup, GN_KEYWORDS_1364_1995, K_pullup
|
output, GN_KEYWORDS_1364_1995, K_output
|
||||||
rcmos, GN_KEYWORDS_1364_1995, K_rcmos
|
parameter, GN_KEYWORDS_1364_1995, K_parameter
|
||||||
real, GN_KEYWORDS_1364_1995, K_real
|
pmos, GN_KEYWORDS_1364_1995, K_pmos
|
||||||
realtime, GN_KEYWORDS_1364_1995, K_realtime
|
posedge, GN_KEYWORDS_1364_1995, K_posedge
|
||||||
reg, GN_KEYWORDS_1364_1995, K_reg
|
potential, GN_KEYWORDS_VAMS_2_3, K_potential
|
||||||
release, GN_KEYWORDS_1364_1995, K_release
|
pow, GN_KEYWORDS_VAMS_2_3, K_pow
|
||||||
repeat, GN_KEYWORDS_1364_1995, K_repeat
|
primitive, GN_KEYWORDS_1364_1995, K_primitive
|
||||||
rnmos, GN_KEYWORDS_1364_1995, K_rnmos
|
pull0, GN_KEYWORDS_1364_1995, K_pull0
|
||||||
rpmos, GN_KEYWORDS_1364_1995, K_rpmos
|
pull1, GN_KEYWORDS_1364_1995, K_pull1
|
||||||
rtran, GN_KEYWORDS_1364_1995, K_rtran
|
pulldown, GN_KEYWORDS_1364_1995, K_pulldown
|
||||||
rtranif0, GN_KEYWORDS_1364_1995, K_rtranif0
|
pullup, GN_KEYWORDS_1364_1995, K_pullup
|
||||||
rtranif1, GN_KEYWORDS_1364_1995, K_rtranif1
|
pulsestyle_onevent, GN_KEYWORDS_1364_2001, K_pulsestyle_onevent
|
||||||
scalared, GN_KEYWORDS_1364_1995, K_scalared
|
pulsestyle_ondetect, GN_KEYWORDS_1364_2001, K_pulsestyle_ondetect
|
||||||
signed, GN_KEYWORDS_1364_2001, K_signed
|
rcmos, GN_KEYWORDS_1364_1995, K_rcmos
|
||||||
sin, GN_KEYWORDS_VAMS_2_3, K_sin
|
real, GN_KEYWORDS_1364_1995, K_real
|
||||||
sinh, GN_KEYWORDS_VAMS_2_3, K_sinh
|
realtime, GN_KEYWORDS_1364_1995, K_realtime
|
||||||
small, GN_KEYWORDS_1364_1995, K_small
|
reg, GN_KEYWORDS_1364_1995, K_reg
|
||||||
specify, GN_KEYWORDS_1364_1995, K_specify
|
release, GN_KEYWORDS_1364_1995, K_release
|
||||||
specparam, GN_KEYWORDS_1364_1995, K_specparam
|
repeat, GN_KEYWORDS_1364_1995, K_repeat
|
||||||
sqrt, GN_KEYWORDS_VAMS_2_3, K_sqrt
|
rnmos, GN_KEYWORDS_1364_1995, K_rnmos
|
||||||
string, GN_KEYWORDS_VAMS_2_3, K_string
|
rpmos, GN_KEYWORDS_1364_1995, K_rpmos
|
||||||
strong0, GN_KEYWORDS_1364_1995, K_strong0
|
rtran, GN_KEYWORDS_1364_1995, K_rtran
|
||||||
strong1, GN_KEYWORDS_1364_1995, K_strong1
|
rtranif0, GN_KEYWORDS_1364_1995, K_rtranif0
|
||||||
supply0, GN_KEYWORDS_1364_1995, K_supply0
|
rtranif1, GN_KEYWORDS_1364_1995, K_rtranif1
|
||||||
supply1, GN_KEYWORDS_1364_1995, K_supply1
|
scalared, GN_KEYWORDS_1364_1995, K_scalared
|
||||||
table, GN_KEYWORDS_1364_1995, K_table
|
showcancelled, GN_KEYWORDS_1364_2001, K_showcancelled
|
||||||
tan, GN_KEYWORDS_VAMS_2_3, K_tan
|
signed, GN_KEYWORDS_1364_2001, K_signed
|
||||||
tanh, GN_KEYWORDS_VAMS_2_3, K_tanh
|
sin, GN_KEYWORDS_VAMS_2_3, K_sin
|
||||||
task, GN_KEYWORDS_1364_1995, K_task
|
sinh, GN_KEYWORDS_VAMS_2_3, K_sinh
|
||||||
time, GN_KEYWORDS_1364_1995, K_time
|
small, GN_KEYWORDS_1364_1995, K_small
|
||||||
tran, GN_KEYWORDS_1364_1995, K_tran
|
specify, GN_KEYWORDS_1364_1995, K_specify
|
||||||
tranif0, GN_KEYWORDS_1364_1995, K_tranif0
|
specparam, GN_KEYWORDS_1364_1995, K_specparam
|
||||||
tranif1, GN_KEYWORDS_1364_1995, K_tranif1
|
sqrt, GN_KEYWORDS_VAMS_2_3, K_sqrt
|
||||||
tri, GN_KEYWORDS_1364_1995, K_tri
|
string, GN_KEYWORDS_VAMS_2_3, K_string
|
||||||
tri0, GN_KEYWORDS_1364_1995, K_tri0
|
strong0, GN_KEYWORDS_1364_1995, K_strong0
|
||||||
tri1, GN_KEYWORDS_1364_1995, K_tri1
|
strong1, GN_KEYWORDS_1364_1995, K_strong1
|
||||||
triand, GN_KEYWORDS_1364_1995, K_triand
|
supply0, GN_KEYWORDS_1364_1995, K_supply0
|
||||||
trior, GN_KEYWORDS_1364_1995, K_trior
|
supply1, GN_KEYWORDS_1364_1995, K_supply1
|
||||||
trireg, GN_KEYWORDS_1364_1995, K_trireg
|
table, GN_KEYWORDS_1364_1995, K_table
|
||||||
units, GN_KEYWORDS_VAMS_2_3, K_units
|
tan, GN_KEYWORDS_VAMS_2_3, K_tan
|
||||||
vectored, GN_KEYWORDS_1364_1995, K_vectored
|
tanh, GN_KEYWORDS_VAMS_2_3, K_tanh
|
||||||
wait, GN_KEYWORDS_1364_1995, K_wait
|
task, GN_KEYWORDS_1364_1995, K_task
|
||||||
wand, GN_KEYWORDS_1364_1995, K_wand
|
time, GN_KEYWORDS_1364_1995, K_time
|
||||||
weak0, GN_KEYWORDS_1364_1995, K_weak0
|
tran, GN_KEYWORDS_1364_1995, K_tran
|
||||||
weak1, GN_KEYWORDS_1364_1995, K_weak1
|
tranif0, GN_KEYWORDS_1364_1995, K_tranif0
|
||||||
while, GN_KEYWORDS_1364_1995, K_while
|
tranif1, GN_KEYWORDS_1364_1995, K_tranif1
|
||||||
wire, GN_KEYWORDS_1364_1995, K_wire
|
tri, GN_KEYWORDS_1364_1995, K_tri
|
||||||
wone, GN_KEYWORDS_1364_1995, K_wone
|
tri0, GN_KEYWORDS_1364_1995, K_tri0
|
||||||
wor, GN_KEYWORDS_1364_1995, K_wor
|
tri1, GN_KEYWORDS_1364_1995, K_tri1
|
||||||
xnor, GN_KEYWORDS_1364_1995, K_xnor
|
triand, GN_KEYWORDS_1364_1995, K_triand
|
||||||
xor, GN_KEYWORDS_1364_1995, K_xor
|
trior, GN_KEYWORDS_1364_1995, K_trior
|
||||||
|
trireg, GN_KEYWORDS_1364_1995, K_trireg
|
||||||
|
units, GN_KEYWORDS_VAMS_2_3, K_units
|
||||||
|
# Reserved for future use!
|
||||||
|
unsigned, GN_KEYWORDS_1364_2001, K_unsigned
|
||||||
|
use, GN_KEYWORDS_1364_2001_CONFIG, K_use
|
||||||
|
uwire, GN_KEYWORDS_1364_2005, K_uwire
|
||||||
|
vectored, GN_KEYWORDS_1364_1995, K_vectored
|
||||||
|
wait, GN_KEYWORDS_1364_1995, K_wait
|
||||||
|
wand, GN_KEYWORDS_1364_1995, K_wand
|
||||||
|
weak0, GN_KEYWORDS_1364_1995, K_weak0
|
||||||
|
weak1, GN_KEYWORDS_1364_1995, K_weak1
|
||||||
|
while, GN_KEYWORDS_1364_1995, K_while
|
||||||
|
wire, GN_KEYWORDS_1364_1995, K_wire
|
||||||
|
# This is the name originally proposed for uwire and is deprecated!
|
||||||
|
wone, GN_KEYWORDS_1364_2005, K_wone
|
||||||
|
wor, GN_KEYWORDS_1364_1995, K_wor
|
||||||
|
xnor, GN_KEYWORDS_1364_1995, K_xnor
|
||||||
|
xor, GN_KEYWORDS_1364_1995, K_xor
|
||||||
%%
|
%%
|
||||||
|
|
||||||
int lexor_keyword_mask = 0;
|
int lexor_keyword_mask = 0;
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,8 @@ PLI_INT32 tf_igetp(PLI_INT32 n, void *obj)
|
||||||
{
|
{
|
||||||
value.format = vpiStringVal;
|
value.format = vpiStringVal;
|
||||||
vpi_get_value(arg_h, &value);
|
vpi_get_value(arg_h, &value);
|
||||||
|
/* The following may generate a compilation warning, but this
|
||||||
|
* functionality is required by some versions of the standard. */
|
||||||
rtn = (int) value.value.str; /* Oh my */
|
rtn = (int) value.value.str; /* Oh my */
|
||||||
} else {
|
} else {
|
||||||
value.format = vpiIntVal;
|
value.format = vpiIntVal;
|
||||||
|
|
|
||||||
78
main.cc
78
main.cc
|
|
@ -77,7 +77,7 @@ extern "C" const char*optarg;
|
||||||
/* Count errors detected in flag processing. */
|
/* Count errors detected in flag processing. */
|
||||||
unsigned flag_errors = 0;
|
unsigned flag_errors = 0;
|
||||||
|
|
||||||
const char*basedir = ".";
|
const char*basedir = strdup(".");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These are the language support control flags. These support which
|
* These are the language support control flags. These support which
|
||||||
|
|
@ -115,6 +115,9 @@ bool warn_implicit = false;
|
||||||
bool warn_timescale = false;
|
bool warn_timescale = false;
|
||||||
bool warn_portbinding = false;
|
bool warn_portbinding = false;
|
||||||
bool warn_inf_loop = false;
|
bool warn_inf_loop = false;
|
||||||
|
bool warn_ob_select = false;
|
||||||
|
bool warn_sens_entire_vec = false;
|
||||||
|
bool warn_sens_entire_arr = false;
|
||||||
|
|
||||||
bool error_implicit = false;
|
bool error_implicit = false;
|
||||||
|
|
||||||
|
|
@ -128,6 +131,13 @@ bool debug_elab_pexpr = false;
|
||||||
bool debug_synth2 = false;
|
bool debug_synth2 = false;
|
||||||
bool debug_optimizer = false;
|
bool debug_optimizer = false;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Miscellaneous flags.
|
||||||
|
*/
|
||||||
|
bool disable_virtual_pins = false;
|
||||||
|
unsigned long array_size_limit = 16777216; // Minimum required by IEEE-1364?
|
||||||
|
unsigned recursive_mod_limit = 10;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Verbose messages enabled.
|
* Verbose messages enabled.
|
||||||
*/
|
*/
|
||||||
|
|
@ -135,6 +145,9 @@ bool verbose_flag = false;
|
||||||
|
|
||||||
unsigned integer_width = 32;
|
unsigned integer_width = 32;
|
||||||
|
|
||||||
|
int def_ts_units = 0;
|
||||||
|
int def_ts_prec = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Keep a heap of identifier strings that I encounter. This is a more
|
* Keep a heap of identifier strings that I encounter. This is a more
|
||||||
* efficient way to allocate those strings.
|
* efficient way to allocate those strings.
|
||||||
|
|
@ -214,6 +227,9 @@ static void process_generation_flag(const char*gen)
|
||||||
} else if (strcmp(gen,"2001") == 0) {
|
} else if (strcmp(gen,"2001") == 0) {
|
||||||
generation_flag = GN_VER2001;
|
generation_flag = GN_VER2001;
|
||||||
|
|
||||||
|
} else if (strcmp(gen,"2001-noconfig") == 0) {
|
||||||
|
generation_flag = GN_VER2001_NOCONFIG;
|
||||||
|
|
||||||
} else if (strcmp(gen,"2005") == 0) {
|
} else if (strcmp(gen,"2005") == 0) {
|
||||||
generation_flag = GN_VER2005;
|
generation_flag = GN_VER2005;
|
||||||
|
|
||||||
|
|
@ -267,7 +283,7 @@ static void parm_to_flagmap(const string&flag)
|
||||||
unsigned off = flag.find('=');
|
unsigned off = flag.find('=');
|
||||||
if (off > flag.size()) {
|
if (off > flag.size()) {
|
||||||
key = flag;
|
key = flag;
|
||||||
value = "";
|
value = strdup("");
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
key = flag.substr(0, off);
|
key = flag.substr(0, off);
|
||||||
|
|
@ -386,6 +402,7 @@ static void read_iconfig_file(const char*ipath)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(buf, "basedir") == 0) {
|
if (strcmp(buf, "basedir") == 0) {
|
||||||
|
free((char *)basedir);
|
||||||
basedir = strdup(cp);
|
basedir = strdup(cp);
|
||||||
|
|
||||||
} else if (strcmp(buf, "debug") == 0) {
|
} else if (strcmp(buf, "debug") == 0) {
|
||||||
|
|
@ -459,6 +476,7 @@ static void read_iconfig_file(const char*ipath)
|
||||||
flags["VPI_MODULE_LIST"] = vpi_module_list;
|
flags["VPI_MODULE_LIST"] = vpi_module_list;
|
||||||
|
|
||||||
} else if (strcmp(buf, "out") == 0) {
|
} else if (strcmp(buf, "out") == 0) {
|
||||||
|
free((char *)flags["-o"]);
|
||||||
flags["-o"] = strdup(cp);
|
flags["-o"] = strdup(cp);
|
||||||
|
|
||||||
} else if (strcmp(buf, "sys_func") == 0) {
|
} else if (strcmp(buf, "sys_func") == 0) {
|
||||||
|
|
@ -476,12 +494,21 @@ static void read_iconfig_file(const char*ipath)
|
||||||
case 'l':
|
case 'l':
|
||||||
warn_inf_loop = true;
|
warn_inf_loop = true;
|
||||||
break;
|
break;
|
||||||
|
case 's':
|
||||||
|
warn_ob_select = true;
|
||||||
|
break;
|
||||||
case 'p':
|
case 'p':
|
||||||
warn_portbinding = true;
|
warn_portbinding = true;
|
||||||
break;
|
break;
|
||||||
case 't':
|
case 't':
|
||||||
warn_timescale = true;
|
warn_timescale = true;
|
||||||
break;
|
break;
|
||||||
|
case 'v':
|
||||||
|
warn_sens_entire_vec = true;
|
||||||
|
break;
|
||||||
|
case 'a':
|
||||||
|
warn_sens_entire_arr = true;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -516,6 +543,7 @@ static void read_iconfig_file(const char*ipath)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fclose(ifile);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern Design* elaborate(list <perm_string> root);
|
extern Design* elaborate(list <perm_string> root);
|
||||||
|
|
@ -542,6 +570,30 @@ inline static void times(struct tms *) { }
|
||||||
inline static double cycles_diff(struct tms *a, struct tms *b) { return 0; }
|
inline static double cycles_diff(struct tms *a, struct tms *b) { return 0; }
|
||||||
#endif // ! defined(HAVE_TIMES)
|
#endif // ! defined(HAVE_TIMES)
|
||||||
|
|
||||||
|
static void EOC_cleanup(void)
|
||||||
|
{
|
||||||
|
cleanup_sys_func_table();
|
||||||
|
|
||||||
|
for (list<const char*>::iterator suf = library_suff.begin() ;
|
||||||
|
suf != library_suff.end() ; suf ++ ) {
|
||||||
|
free((char *)*suf);
|
||||||
|
}
|
||||||
|
library_suff.clear();
|
||||||
|
|
||||||
|
free((char *) basedir);
|
||||||
|
free(ivlpp_string);
|
||||||
|
free(depfile_name);
|
||||||
|
|
||||||
|
for (map<string, const char*>::iterator flg = flags.begin() ;
|
||||||
|
flg != flags.end() ; flg ++ ) {
|
||||||
|
free((char *)flg->second);
|
||||||
|
}
|
||||||
|
flags.clear();
|
||||||
|
|
||||||
|
lex_strings.cleanup();
|
||||||
|
filename_strings.cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char*argv[])
|
int main(int argc, char*argv[])
|
||||||
{
|
{
|
||||||
bool help_flag = false;
|
bool help_flag = false;
|
||||||
|
|
@ -554,11 +606,11 @@ int main(int argc, char*argv[])
|
||||||
|
|
||||||
struct tms cycles[5];
|
struct tms cycles[5];
|
||||||
|
|
||||||
library_suff.push_back(".v");
|
library_suff.push_back(strdup(".v"));
|
||||||
|
|
||||||
vpi_module_list = strdup("system");
|
vpi_module_list = strdup("system");
|
||||||
flags["VPI_MODULE_LIST"] = vpi_module_list;
|
flags["VPI_MODULE_LIST"] = vpi_module_list;
|
||||||
flags["-o"] = "a.out";
|
flags["-o"] = strdup("a.out");
|
||||||
min_typ_max_flag = TYP;
|
min_typ_max_flag = TYP;
|
||||||
min_typ_max_warn = 10;
|
min_typ_max_warn = 10;
|
||||||
|
|
||||||
|
|
@ -650,9 +702,10 @@ int main(int argc, char*argv[])
|
||||||
lexor_keyword_mask |= GN_KEYWORDS_1364_1995;
|
lexor_keyword_mask |= GN_KEYWORDS_1364_1995;
|
||||||
break;
|
break;
|
||||||
case GN_VER2001:
|
case GN_VER2001:
|
||||||
|
lexor_keyword_mask |= GN_KEYWORDS_1364_2001_CONFIG;
|
||||||
|
case GN_VER2001_NOCONFIG:
|
||||||
lexor_keyword_mask |= GN_KEYWORDS_1364_1995;
|
lexor_keyword_mask |= GN_KEYWORDS_1364_1995;
|
||||||
lexor_keyword_mask |= GN_KEYWORDS_1364_2001;
|
lexor_keyword_mask |= GN_KEYWORDS_1364_2001;
|
||||||
lexor_keyword_mask |= GN_KEYWORDS_1364_2001_CONFIG;
|
|
||||||
break;
|
break;
|
||||||
case GN_VER2005:
|
case GN_VER2005:
|
||||||
lexor_keyword_mask |= GN_KEYWORDS_1364_1995;
|
lexor_keyword_mask |= GN_KEYWORDS_1364_1995;
|
||||||
|
|
@ -680,6 +733,9 @@ int main(int argc, char*argv[])
|
||||||
case GN_VER1995:
|
case GN_VER1995:
|
||||||
cout << "IEEE1364-1995";
|
cout << "IEEE1364-1995";
|
||||||
break;
|
break;
|
||||||
|
case GN_VER2001_NOCONFIG:
|
||||||
|
cout << "IEEE1364-2001-noconfig";
|
||||||
|
break;
|
||||||
case GN_VER2001:
|
case GN_VER2001:
|
||||||
cout << "IEEE1364-2001";
|
cout << "IEEE1364-2001";
|
||||||
break;
|
break;
|
||||||
|
|
@ -709,7 +765,17 @@ int main(int argc, char*argv[])
|
||||||
cout << endl << "PARSING INPUT" << endl;
|
cout << endl << "PARSING INPUT" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *flag_tmp = flags["DISABLE_VIRTUAL_PINS"];
|
||||||
|
if (flag_tmp) disable_virtual_pins = strcmp(flag_tmp,"true")==0;
|
||||||
|
|
||||||
|
flag_tmp = flags["ARRAY_SIZE_LIMIT"];
|
||||||
|
if (flag_tmp) array_size_limit = strtoul(flag_tmp,NULL,0);
|
||||||
|
|
||||||
|
flag_tmp = flags["RECURSIVE_MOD_LIMIT"];
|
||||||
|
if (flag_tmp) recursive_mod_limit = strtoul(flag_tmp,NULL,0);
|
||||||
|
|
||||||
/* Parse the input. Make the pform. */
|
/* Parse the input. Make the pform. */
|
||||||
|
pform_set_timescale(def_ts_units, def_ts_prec, 0, 0);
|
||||||
int rc = pform_parse(argv[optind]);
|
int rc = pform_parse(argv[optind]);
|
||||||
|
|
||||||
if (pf_path) {
|
if (pf_path) {
|
||||||
|
|
@ -906,6 +972,8 @@ int main(int argc, char*argv[])
|
||||||
<< endl;
|
<< endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
delete des;
|
||||||
|
EOC_cleanup();
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
errors_summary:
|
errors_summary:
|
||||||
|
|
|
||||||
40
mingw.txt
40
mingw.txt
|
|
@ -1,3 +1,8 @@
|
||||||
|
Please NOTE:
|
||||||
|
|
||||||
|
These directions are slightly outdated and need to be updated.
|
||||||
|
The plan is to rewrite all this using the latest MinGW at
|
||||||
|
some time in the not too distant future (CR Aug. 2009)
|
||||||
|
|
||||||
|
|
||||||
MINGW PORT OF ICARUS VERILOG
|
MINGW PORT OF ICARUS VERILOG
|
||||||
|
|
@ -49,7 +54,7 @@ critical, but these are the versions I use.
|
||||||
Mingw32-5.x <http://www.mingw.org>
|
Mingw32-5.x <http://www.mingw.org>
|
||||||
... including the sub-packages binutils, gcc-core and gcc-g++
|
... including the sub-packages binutils, gcc-core and gcc-g++
|
||||||
if you are given the option.
|
if you are given the option.
|
||||||
readline-4.2-20010727.zip <http://mingwrep.sourceforge.net>
|
readline-5.0-1 <http://gnuwin32.sourceforge.net>
|
||||||
bzip2-1.0.3 <http://gnuwin32.sourceforge.net>
|
bzip2-1.0.3 <http://gnuwin32.sourceforge.net>
|
||||||
zlib-1.2.3 <http://gnuwin32.sourceforge.net>
|
zlib-1.2.3 <http://gnuwin32.sourceforge.net>
|
||||||
gperf-3.0.1 <http://gnuwin32.sourceforge.net>
|
gperf-3.0.1 <http://gnuwin32.sourceforge.net>
|
||||||
|
|
@ -79,7 +84,7 @@ Download the msys-1.x.x.exe and msysdtc-1.x.x.exe binaries. These are
|
||||||
self-installing packages. Install msys first, and then msysDTC. Most
|
self-installing packages. Install msys first, and then msysDTC. Most
|
||||||
likely, you want to install them in c:/msys. (The msysDTK is installed
|
likely, you want to install them in c:/msys. (The msysDTK is installed
|
||||||
in the same location, as it is an add-on.)
|
in the same location, as it is an add-on.)
|
||||||
|
|
||||||
This install should be easy and reliable.
|
This install should be easy and reliable.
|
||||||
|
|
||||||
The installation will leave an "msys" icon on your desktop and in the
|
The installation will leave an "msys" icon on your desktop and in the
|
||||||
|
|
@ -110,29 +115,6 @@ Finally, as part of installing the mingw32 compilers, remember to add
|
||||||
the mingw/bin directory to your path. You will need that to be able to
|
the mingw/bin directory to your path. You will need that to be able to
|
||||||
find the compilers later.
|
find the compilers later.
|
||||||
|
|
||||||
* Install Mingw32 Packages
|
|
||||||
|
|
||||||
There is a collection of precompiled libraries and add-on packages
|
|
||||||
that are intended for use with the Mingw32 compiler. These do not come
|
|
||||||
with simplified Windows installers, but they are pretty easy to
|
|
||||||
install by hand. Icarus Verilog uses the readline-4.2 package from
|
|
||||||
that collection.
|
|
||||||
|
|
||||||
Since I installed Mingw32 in c:\mingw, I also created a
|
|
||||||
Mingw-packages directory called c:\mingw-packages. The install, then,
|
|
||||||
is as easy as this:
|
|
||||||
|
|
||||||
<msys shell>
|
|
||||||
$ cd c:/mingw-packages
|
|
||||||
$ unzip readline-4.2-20010727.zip
|
|
||||||
[lots of inflating...]
|
|
||||||
|
|
||||||
There is no need to adjust your execution path for this package as we
|
|
||||||
are only using a library out of here. However, do remember the
|
|
||||||
directory name, as you will need it later.
|
|
||||||
|
|
||||||
Done. On to the next packages.
|
|
||||||
|
|
||||||
* Install GnuWin32 Packages
|
* Install GnuWin32 Packages
|
||||||
|
|
||||||
The GnuWin32 project is a collections of open source programs and
|
The GnuWin32 project is a collections of open source programs and
|
||||||
|
|
@ -148,6 +130,7 @@ You will need these gnuwin32 packages to compile Icarus Verilog:
|
||||||
gperf-3.0.1.exe
|
gperf-3.0.1.exe
|
||||||
bison-2.1.exe
|
bison-2.1.exe
|
||||||
flex-2.5.4a.exe
|
flex-2.5.4a.exe
|
||||||
|
readline-5.0-1.exe
|
||||||
|
|
||||||
I suggest creating a common directory for holding all your gnuwin32
|
I suggest creating a common directory for holding all your gnuwin32
|
||||||
packages. I use C:\gnuwin32. The download page at the gnuwin32 site
|
packages. I use C:\gnuwin32. The download page at the gnuwin32 site
|
||||||
|
|
@ -218,8 +201,8 @@ without white space.
|
||||||
Now, configure the source to make the makefiles and configuration
|
Now, configure the source to make the makefiles and configuration
|
||||||
details. Run these commands:
|
details. Run these commands:
|
||||||
|
|
||||||
$ CPPFLAGS="-Ic:/gnuwin32/include -Ic:/mingw-packages/include"
|
$ CPPFLAGS="-Ic:/gnuwin32/include
|
||||||
$ LDFLAGS="-Lc:/gnuwin32/lib -Lc:/mingw-packages/lib"
|
$ LDFLAGS="-Lc:/gnuwin32/lib
|
||||||
$ export CPPFLAGS LDFLAGS
|
$ export CPPFLAGS LDFLAGS
|
||||||
$ ./configure --prefix=c:/iverilog
|
$ ./configure --prefix=c:/iverilog
|
||||||
|
|
||||||
|
|
@ -271,7 +254,8 @@ You may find that you need to put some of the prerequisite DLLs into
|
||||||
the d:\iverilog\bin directory. These include:
|
the d:\iverilog\bin directory. These include:
|
||||||
|
|
||||||
c:\mingw\bin\mingw10.dll
|
c:\mingw\bin\mingw10.dll
|
||||||
c:\mingw-packages\bin\libreadline.dll
|
c:\gnuwin32\bin\readline.dll
|
||||||
|
c:\gnuwin32\bin\history.dll
|
||||||
c:\gnuwin32\bin\bzip2.dll
|
c:\gnuwin32\bin\bzip2.dll
|
||||||
c:\gnuwin32\bin\zlib.dll
|
c:\gnuwin32\bin\zlib.dll
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000-2007 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2000-2009 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -490,7 +490,7 @@ void NetScope::evaluate_parameter_logic_(Design*des, param_ref_t cur)
|
||||||
void NetScope::evaluate_parameter_real_(Design*des, param_ref_t cur)
|
void NetScope::evaluate_parameter_real_(Design*des, param_ref_t cur)
|
||||||
{
|
{
|
||||||
NetExpr*expr = (*cur).second.expr;
|
NetExpr*expr = (*cur).second.expr;
|
||||||
assert(expr);
|
if (expr == NULL) return; // This is an invalid parameter so return.
|
||||||
|
|
||||||
NetECReal*res = 0;
|
NetECReal*res = 0;
|
||||||
eval_expr(expr);
|
eval_expr(expr);
|
||||||
|
|
|
||||||
17
net_expr.cc
17
net_expr.cc
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2008 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2002-2009 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -257,15 +257,13 @@ ivl_variable_type_t NetEBMinMax::expr_type() const
|
||||||
NetEBMult::NetEBMult(char op__, NetExpr*l, NetExpr*r)
|
NetEBMult::NetEBMult(char op__, NetExpr*l, NetExpr*r)
|
||||||
: NetEBinary(op__, l, r)
|
: NetEBinary(op__, l, r)
|
||||||
{
|
{
|
||||||
if (expr_type() == IVL_VT_REAL)
|
if (expr_type() == IVL_VT_REAL) {
|
||||||
expr_width(1);
|
expr_width(1);
|
||||||
else
|
|
||||||
expr_width(l->expr_width() + r->expr_width());
|
|
||||||
|
|
||||||
if (expr_type() == IVL_VT_REAL)
|
|
||||||
cast_signed(true);
|
cast_signed(true);
|
||||||
else
|
} else {
|
||||||
|
expr_width(l->expr_width() + r->expr_width());
|
||||||
cast_signed(l->has_sign() && r->has_sign());
|
cast_signed(l->has_sign() && r->has_sign());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NetEBMult::~NetEBMult()
|
NetEBMult::~NetEBMult()
|
||||||
|
|
@ -294,8 +292,8 @@ NetEBPow::NetEBPow(char op__, NetExpr*l, NetExpr*r)
|
||||||
: NetEBinary(op__, l, r)
|
: NetEBinary(op__, l, r)
|
||||||
{
|
{
|
||||||
assert(op__ == 'p');
|
assert(op__ == 'p');
|
||||||
/* This is incorrect! a * (2^b - 1) is close. */
|
/* You could need up to a * (2^b - 1) bits. */
|
||||||
expr_width(l->expr_width()+r->expr_width());
|
expr_width(l->expr_width());
|
||||||
cast_signed(l->has_sign() || r->has_sign());
|
cast_signed(l->has_sign() || r->has_sign());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -438,6 +436,7 @@ NetECReal::NetECReal(const verireal&val)
|
||||||
: value_(val)
|
: value_(val)
|
||||||
{
|
{
|
||||||
expr_width(1);
|
expr_width(1);
|
||||||
|
cast_signed(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
NetECReal::~NetECReal()
|
NetECReal::~NetECReal()
|
||||||
|
|
|
||||||
|
|
@ -173,7 +173,7 @@ void Link::unlink()
|
||||||
|
|
||||||
bool Link::is_equal(const Link&that) const
|
bool Link::is_equal(const Link&that) const
|
||||||
{
|
{
|
||||||
return (node_ == that.node_) && (pin_ == that.pin_);
|
return (get_obj() == that.get_obj()) && (get_pin() == that.get_pin());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Link::is_linked() const
|
bool Link::is_linked() const
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@
|
||||||
|
|
||||||
# include <cassert>
|
# include <cassert>
|
||||||
# include <typeinfo>
|
# include <typeinfo>
|
||||||
|
# include "compiler.h"
|
||||||
# include "netlist.h"
|
# include "netlist.h"
|
||||||
# include "netmisc.h"
|
# include "netmisc.h"
|
||||||
|
|
||||||
|
|
@ -114,6 +115,11 @@ NexusSet* NetESelect::nex_input(bool rem_out)
|
||||||
}
|
}
|
||||||
result->add(*tmp);
|
result->add(*tmp);
|
||||||
delete tmp;
|
delete tmp;
|
||||||
|
/* See the comment for NetESignal below. */
|
||||||
|
if (base_ && warn_sens_entire_vec) {
|
||||||
|
cerr << get_fileline() << ": warning: @* is sensitive to all "
|
||||||
|
"bits in '" << *expr_ << "'." << endl;
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -133,7 +139,25 @@ NexusSet* NetESFunc::nex_input(bool rem_out)
|
||||||
|
|
||||||
NexusSet* NetESignal::nex_input(bool rem_out)
|
NexusSet* NetESignal::nex_input(bool rem_out)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
* This is not what I would expect for the various selects (bit,
|
||||||
|
* part, index, array). This code adds all the bits/array words
|
||||||
|
* instead of building the appropriate select and then using it
|
||||||
|
* as the trigger. Other simulators also add everything.
|
||||||
|
*/
|
||||||
NexusSet*result = new NexusSet;
|
NexusSet*result = new NexusSet;
|
||||||
|
/* If we have an array index add it to the sensitivity list. */
|
||||||
|
if (word_) {
|
||||||
|
NexusSet*tmp;
|
||||||
|
tmp = word_->nex_input(rem_out);
|
||||||
|
result->add(*tmp);
|
||||||
|
delete tmp;
|
||||||
|
if (warn_sens_entire_arr) {
|
||||||
|
cerr << get_fileline() << ": warning: @* is sensitive to all "
|
||||||
|
<< net_->array_count() << " words in array '"
|
||||||
|
<< name() << "'." << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
for (unsigned idx = 0 ; idx < net_->pin_count() ; idx += 1)
|
for (unsigned idx = 0 ; idx < net_->pin_count() ; idx += 1)
|
||||||
result->add(net_->pin(idx).nexus());
|
result->add(net_->pin(idx).nexus());
|
||||||
|
|
||||||
|
|
|
||||||
54
net_scope.cc
54
net_scope.cc
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000-2008 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2000-2009 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -41,17 +41,20 @@ NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t)
|
||||||
events_ = 0;
|
events_ = 0;
|
||||||
lcounter_ = 0;
|
lcounter_ = 0;
|
||||||
is_auto_ = false;
|
is_auto_ = false;
|
||||||
|
is_cell_ = false;
|
||||||
|
|
||||||
if (up) {
|
if (up) {
|
||||||
default_nettype_ = up->default_nettype();
|
default_nettype_ = up->default_nettype();
|
||||||
time_unit_ = up->time_unit();
|
time_unit_ = up->time_unit();
|
||||||
time_prec_ = up->time_precision();
|
time_prec_ = up->time_precision();
|
||||||
|
time_from_timescale_ = up->time_from_timescale();
|
||||||
sib_ = up_->sub_;
|
sib_ = up_->sub_;
|
||||||
up_->sub_ = this;
|
up_->sub_ = this;
|
||||||
} else {
|
} else {
|
||||||
default_nettype_ = NetNet::NONE;
|
default_nettype_ = NetNet::NONE;
|
||||||
time_unit_ = 0;
|
time_unit_ = 0;
|
||||||
time_prec_ = 0;
|
time_prec_ = 0;
|
||||||
|
time_from_timescale_ = false;
|
||||||
assert(t == MODULE);
|
assert(t == MODULE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -230,6 +233,31 @@ NetScope::TYPE NetScope::type() const
|
||||||
return type_;
|
return type_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NetScope::print_type(ostream&stream) const
|
||||||
|
{
|
||||||
|
switch (type_) {
|
||||||
|
case BEGIN_END:
|
||||||
|
stream << "sequential block";
|
||||||
|
break;
|
||||||
|
case FORK_JOIN:
|
||||||
|
stream << "parallel block";
|
||||||
|
break;
|
||||||
|
case FUNC:
|
||||||
|
stream << "function";
|
||||||
|
break;
|
||||||
|
case MODULE:
|
||||||
|
stream << "module <" << (module_name_ ? module_name_.str() : "")
|
||||||
|
<< "> instance";
|
||||||
|
break;
|
||||||
|
case TASK:
|
||||||
|
stream << "task";
|
||||||
|
break;
|
||||||
|
case GENBLOCK:
|
||||||
|
stream << "generate block";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void NetScope::set_task_def(NetTaskDef*def)
|
void NetScope::set_task_def(NetTaskDef*def)
|
||||||
{
|
{
|
||||||
assert( type_ == TASK );
|
assert( type_ == TASK );
|
||||||
|
|
@ -295,6 +323,11 @@ void NetScope::time_precision(int val)
|
||||||
time_prec_ = val;
|
time_prec_ = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NetScope::time_from_timescale(bool val)
|
||||||
|
{
|
||||||
|
time_from_timescale_ = val;
|
||||||
|
}
|
||||||
|
|
||||||
int NetScope::time_unit() const
|
int NetScope::time_unit() const
|
||||||
{
|
{
|
||||||
return time_unit_;
|
return time_unit_;
|
||||||
|
|
@ -305,6 +338,11 @@ int NetScope::time_precision() const
|
||||||
return time_prec_;
|
return time_prec_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool NetScope::time_from_timescale() const
|
||||||
|
{
|
||||||
|
return time_from_timescale_;
|
||||||
|
}
|
||||||
|
|
||||||
void NetScope::default_nettype(NetNet::Type nt)
|
void NetScope::default_nettype(NetNet::Type nt)
|
||||||
{
|
{
|
||||||
default_nettype_ = nt;
|
default_nettype_ = nt;
|
||||||
|
|
@ -357,6 +395,20 @@ NetEvent* NetScope::find_event(perm_string name)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NetScope::add_genvar(perm_string name, LineInfo *li)
|
||||||
|
{
|
||||||
|
assert((type_ == MODULE) || (type_ == GENBLOCK));
|
||||||
|
genvars_[name] = li;
|
||||||
|
}
|
||||||
|
|
||||||
|
LineInfo* NetScope::find_genvar(perm_string name)
|
||||||
|
{
|
||||||
|
if (genvars_.find(name) != genvars_.end())
|
||||||
|
return genvars_[name];
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void NetScope::add_signal(NetNet*net)
|
void NetScope::add_signal(NetNet*net)
|
||||||
{
|
{
|
||||||
signals_map_[net->name()]=net;
|
signals_map_[net->name()]=net;
|
||||||
|
|
|
||||||
127
netlist.cc
127
netlist.cc
|
|
@ -78,8 +78,8 @@ ostream& operator<< (ostream&o, NetNet::Type t)
|
||||||
case NetNet::WIRE:
|
case NetNet::WIRE:
|
||||||
o << "wire";
|
o << "wire";
|
||||||
break;
|
break;
|
||||||
case NetNet::WONE:
|
case NetNet::UWIRE:
|
||||||
o << "wone";
|
o << "uwire";
|
||||||
}
|
}
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
@ -172,26 +172,51 @@ Link* find_next_output(Link*lnk)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
NetPins::NetPins(unsigned npins)
|
void NetPins::devirtualize_pins(void)
|
||||||
: npins_(npins)
|
|
||||||
{
|
{
|
||||||
|
if (pins_) return;
|
||||||
|
if (npins_ > array_size_limit) {
|
||||||
|
cerr << get_fileline() << ": error: pin count " << npins_ <<
|
||||||
|
" exceeds " << array_size_limit <<
|
||||||
|
" (set by -pARRAY_SIZE_LIMIT)" << endl;
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
if (debug_optimizer && npins_ > 1000) cerr << "debug: devirtualizing " << npins_ << " pins." << endl;
|
||||||
|
|
||||||
pins_ = new Link[npins_];
|
pins_ = new Link[npins_];
|
||||||
pins_[0].pin_zero_ = true;
|
pins_[0].pin_zero_ = true;
|
||||||
pins_[0].node_ = this;
|
pins_[0].node_ = this;
|
||||||
|
pins_[0].dir_ = default_dir_;
|
||||||
|
pins_[0].init_ = default_init_;
|
||||||
|
|
||||||
for (unsigned idx = 1 ; idx < npins_ ; idx += 1) {
|
for (unsigned idx = 1 ; idx < npins_ ; idx += 1) {
|
||||||
pins_[idx].pin_zero_ = false;
|
pins_[idx].pin_zero_ = false;
|
||||||
pins_[idx].pin_ = idx;
|
pins_[idx].pin_ = idx;
|
||||||
|
pins_[idx].dir_ = default_dir_;
|
||||||
|
pins_[idx].init_ = default_init_;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool NetPins::pins_are_virtual(void) const
|
||||||
|
{
|
||||||
|
return pins_ == NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
NetPins::NetPins(unsigned npins)
|
||||||
|
: npins_(npins)
|
||||||
|
{
|
||||||
|
pins_ = NULL; // Wait until someone asks.
|
||||||
|
if (disable_virtual_pins) devirtualize_pins(); // Ask. Bummer.
|
||||||
|
}
|
||||||
|
|
||||||
NetPins::~NetPins()
|
NetPins::~NetPins()
|
||||||
{
|
{
|
||||||
delete[]pins_;
|
if (pins_) delete[]pins_;
|
||||||
}
|
}
|
||||||
|
|
||||||
Link& NetPins::pin(unsigned idx)
|
Link& NetPins::pin(unsigned idx)
|
||||||
{
|
{
|
||||||
|
if (!pins_) devirtualize_pins();
|
||||||
if (idx >= npins_) {
|
if (idx >= npins_) {
|
||||||
cerr << get_fileline() << ": internal error: pin("<<idx<<")"
|
cerr << get_fileline() << ": internal error: pin("<<idx<<")"
|
||||||
<< " out of bounds("<<npins_<<")" << endl;
|
<< " out of bounds("<<npins_<<")" << endl;
|
||||||
|
|
@ -207,11 +232,27 @@ Link& NetPins::pin(unsigned idx)
|
||||||
|
|
||||||
const Link& NetPins::pin(unsigned idx) const
|
const Link& NetPins::pin(unsigned idx) const
|
||||||
{
|
{
|
||||||
|
if (!pins_ && !disable_virtual_pins) {
|
||||||
|
cerr << get_fileline() << ": internal error: pin is unexpectedly"
|
||||||
|
" virtual, try again with -pDISABLE_VIRTUAL_PINS=true" << endl;
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
assert(pins_);
|
||||||
assert(idx < npins_);
|
assert(idx < npins_);
|
||||||
assert(idx == 0? pins_[0].pin_zero_ : pins_[idx].pin_==idx);
|
assert(idx == 0? pins_[0].pin_zero_ : pins_[idx].pin_==idx);
|
||||||
return pins_[idx];
|
return pins_[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NetPins::set_default_dir(Link::DIR d)
|
||||||
|
{
|
||||||
|
default_dir_ = d;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NetPins::set_default_init(verinum::V val)
|
||||||
|
{
|
||||||
|
default_init_ = val;
|
||||||
|
}
|
||||||
|
|
||||||
bool NetPins::is_linked(void)
|
bool NetPins::is_linked(void)
|
||||||
{
|
{
|
||||||
bool linked_flag = false;
|
bool linked_flag = false;
|
||||||
|
|
@ -228,6 +269,11 @@ bool NetPins::is_linked(void)
|
||||||
NetObj::NetObj(NetScope*s, perm_string n, unsigned np)
|
NetObj::NetObj(NetScope*s, perm_string n, unsigned np)
|
||||||
: NetPins(np), scope_(s), name_(n), delay1_(0), delay2_(0), delay3_(0)
|
: NetPins(np), scope_(s), name_(n), delay1_(0), delay2_(0), delay3_(0)
|
||||||
{
|
{
|
||||||
|
/* Don't
|
||||||
|
ivl_assert(*this, np > 0);
|
||||||
|
* because it would happen before we get to print a useful
|
||||||
|
* message in the NetNet constructor
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
NetObj::~NetObj()
|
NetObj::~NetObj()
|
||||||
|
|
@ -269,6 +315,9 @@ NetBranch::~NetBranch()
|
||||||
NetBus::NetBus(NetScope*s, unsigned pin_count__)
|
NetBus::NetBus(NetScope*s, unsigned pin_count__)
|
||||||
: NetObj(s, perm_string::literal(""), pin_count__)
|
: NetObj(s, perm_string::literal(""), pin_count__)
|
||||||
{
|
{
|
||||||
|
for (unsigned idx = 0 ; idx <pin_count__ ; idx += 1) {
|
||||||
|
pin(idx).set_dir(Link::PASSIVE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NetBus::~NetBus()
|
NetBus::~NetBus()
|
||||||
|
|
@ -442,8 +491,8 @@ const Link& NetDelaySrc::condit_pin() const
|
||||||
NetNet::NetNet(NetScope*s, perm_string n, Type t, unsigned npins)
|
NetNet::NetNet(NetScope*s, perm_string n, Type t, unsigned npins)
|
||||||
: NetObj(s, n, 1),
|
: NetObj(s, n, 1),
|
||||||
type_(t), port_type_(NOT_A_PORT), data_type_(IVL_VT_NO_TYPE),
|
type_(t), port_type_(NOT_A_PORT), data_type_(IVL_VT_NO_TYPE),
|
||||||
signed_(false), isint_(false), discipline_(0), msb_(npins-1), lsb_(0),
|
signed_(false), isint_(false), is_scalar_(false),
|
||||||
dimensions_(0),
|
discipline_(0), msb_(npins-1), lsb_(0), dimensions_(0),
|
||||||
s0_(0), e0_(0), local_flag_(false), eref_count_(0), lref_count_(0)
|
s0_(0), e0_(0), local_flag_(false), eref_count_(0), lref_count_(0)
|
||||||
{
|
{
|
||||||
assert(s);
|
assert(s);
|
||||||
|
|
@ -479,7 +528,11 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t, unsigned npins)
|
||||||
|
|
||||||
void NetNet::initialize_value_and_dir(verinum::V init_value, Link::DIR dir)
|
void NetNet::initialize_value_and_dir(verinum::V init_value, Link::DIR dir)
|
||||||
{
|
{
|
||||||
if (1) {
|
if (pins_are_virtual()) {
|
||||||
|
if (0) cerr << "NetNet setting Link default value and dir" << endl;
|
||||||
|
set_default_init(init_value);
|
||||||
|
set_default_dir(dir);
|
||||||
|
} else {
|
||||||
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
|
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
|
||||||
pin(idx).set_dir(dir);
|
pin(idx).set_dir(dir);
|
||||||
pin(idx).set_init(init_value);
|
pin(idx).set_init(init_value);
|
||||||
|
|
@ -491,7 +544,8 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t,
|
||||||
long ms, long ls)
|
long ms, long ls)
|
||||||
: NetObj(s, n, 1), type_(t),
|
: NetObj(s, n, 1), type_(t),
|
||||||
port_type_(NOT_A_PORT), data_type_(IVL_VT_NO_TYPE), signed_(false),
|
port_type_(NOT_A_PORT), data_type_(IVL_VT_NO_TYPE), signed_(false),
|
||||||
isint_(false), discipline_(0), msb_(ms), lsb_(ls), dimensions_(0), s0_(0), e0_(0),
|
isint_(false), is_scalar_(false), discipline_(0), msb_(ms), lsb_(ls),
|
||||||
|
dimensions_(0), s0_(0), e0_(0),
|
||||||
local_flag_(false), eref_count_(0), lref_count_(0)
|
local_flag_(false), eref_count_(0), lref_count_(0)
|
||||||
{
|
{
|
||||||
assert(s);
|
assert(s);
|
||||||
|
|
@ -524,10 +578,16 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t,
|
||||||
|
|
||||||
static unsigned calculate_count(long s, long e)
|
static unsigned calculate_count(long s, long e)
|
||||||
{
|
{
|
||||||
if (s >= e)
|
unsigned long r;
|
||||||
return s - e + 1;
|
if (s >= e) {
|
||||||
else
|
r = s - e;
|
||||||
return e - s + 1;
|
} else {
|
||||||
|
r = e - s;
|
||||||
|
}
|
||||||
|
if (r >= UINT_MAX) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return r + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
NetNet::NetNet(NetScope*s, perm_string n, Type t,
|
NetNet::NetNet(NetScope*s, perm_string n, Type t,
|
||||||
|
|
@ -535,10 +595,15 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t,
|
||||||
: NetObj(s, n, calculate_count(array_s, array_e)),
|
: NetObj(s, n, calculate_count(array_s, array_e)),
|
||||||
type_(t), port_type_(NOT_A_PORT),
|
type_(t), port_type_(NOT_A_PORT),
|
||||||
data_type_(IVL_VT_NO_TYPE), signed_(false), isint_(false),
|
data_type_(IVL_VT_NO_TYPE), signed_(false), isint_(false),
|
||||||
discipline_(0), msb_(ms), lsb_(ls), dimensions_(1), s0_(array_s), e0_(array_e),
|
is_scalar_(false), discipline_(0), msb_(ms), lsb_(ls),
|
||||||
|
dimensions_(1), s0_(array_s), e0_(array_e),
|
||||||
local_flag_(false), eref_count_(0), lref_count_(0)
|
local_flag_(false), eref_count_(0), lref_count_(0)
|
||||||
{
|
{
|
||||||
assert(s);
|
ivl_assert(*this, s);
|
||||||
|
if (pin_count() == 0) {
|
||||||
|
cerr << "Array too big [" << array_s << ":" << array_e << "]" << endl;
|
||||||
|
ivl_assert(*this, 0);
|
||||||
|
}
|
||||||
|
|
||||||
verinum::V init_value = verinum::Vz;
|
verinum::V init_value = verinum::Vz;
|
||||||
Link::DIR dir = Link::PASSIVE;
|
Link::DIR dir = Link::PASSIVE;
|
||||||
|
|
@ -664,6 +729,16 @@ void NetNet::set_isint(bool flag)
|
||||||
isint_ = flag;
|
isint_ = flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool NetNet::get_scalar() const
|
||||||
|
{
|
||||||
|
return is_scalar_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NetNet::set_scalar(bool flag)
|
||||||
|
{
|
||||||
|
is_scalar_ = flag;
|
||||||
|
}
|
||||||
|
|
||||||
ivl_discipline_t NetNet::get_discipline() const
|
ivl_discipline_t NetNet::get_discipline() const
|
||||||
{
|
{
|
||||||
return discipline_;
|
return discipline_;
|
||||||
|
|
@ -732,7 +807,9 @@ bool NetNet::array_addr_swapped() const
|
||||||
|
|
||||||
unsigned NetNet::array_count() const
|
unsigned NetNet::array_count() const
|
||||||
{
|
{
|
||||||
return calculate_count(s0_, e0_);
|
unsigned c = calculate_count(s0_, e0_);
|
||||||
|
ivl_assert(*this, c > 0);
|
||||||
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NetNet::array_index_is_valid(long sb) const
|
bool NetNet::array_index_is_valid(long sb) const
|
||||||
|
|
@ -810,7 +887,6 @@ NetPartSelect::NetPartSelect(NetNet*sig, unsigned off, unsigned wid,
|
||||||
: NetNode(sig->scope(), sig->scope()->local_symbol(), 2),
|
: NetNode(sig->scope(), sig->scope()->local_symbol(), 2),
|
||||||
off_(off), wid_(wid), dir_(dir__)
|
off_(off), wid_(wid), dir_(dir__)
|
||||||
{
|
{
|
||||||
connect(pin(1), sig->pin(0));
|
|
||||||
set_line(*sig);
|
set_line(*sig);
|
||||||
|
|
||||||
switch (dir_) {
|
switch (dir_) {
|
||||||
|
|
@ -823,6 +899,8 @@ NetPartSelect::NetPartSelect(NetNet*sig, unsigned off, unsigned wid,
|
||||||
pin(1).set_dir(Link::OUTPUT);
|
pin(1).set_dir(Link::OUTPUT);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
connect(pin(1), sig->pin(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
NetPartSelect::NetPartSelect(NetNet*sig, NetNet*sel,
|
NetPartSelect::NetPartSelect(NetNet*sig, NetNet*sel,
|
||||||
|
|
@ -830,20 +908,19 @@ NetPartSelect::NetPartSelect(NetNet*sig, NetNet*sel,
|
||||||
: NetNode(sig->scope(), sig->scope()->local_symbol(), 3),
|
: NetNode(sig->scope(), sig->scope()->local_symbol(), 3),
|
||||||
off_(0), wid_(wid), dir_(VP)
|
off_(0), wid_(wid), dir_(VP)
|
||||||
{
|
{
|
||||||
connect(pin(1), sig->pin(0));
|
|
||||||
connect(pin(2), sel->pin(0));
|
|
||||||
|
|
||||||
switch (dir_) {
|
switch (dir_) {
|
||||||
case NetPartSelect::VP:
|
case NetPartSelect::VP:
|
||||||
pin(0).set_dir(Link::OUTPUT);
|
pin(0).set_dir(Link::OUTPUT);
|
||||||
pin(1).set_dir(Link::INPUT);
|
pin(1).set_dir(Link::INPUT);
|
||||||
break;
|
break;
|
||||||
case NetPartSelect::PV:
|
case NetPartSelect::PV:
|
||||||
pin(0).set_dir(Link::INPUT);
|
/* Only a vector to part can be a variable select. */
|
||||||
pin(1).set_dir(Link::OUTPUT);
|
assert(0);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
pin(2).set_dir(Link::INPUT);
|
pin(2).set_dir(Link::INPUT);
|
||||||
|
|
||||||
|
connect(pin(1), sig->pin(0));
|
||||||
|
connect(pin(2), sel->pin(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
NetPartSelect::~NetPartSelect()
|
NetPartSelect::~NetPartSelect()
|
||||||
|
|
@ -2271,12 +2348,12 @@ NetNet* NetESignal::sig()
|
||||||
return net_;
|
return net_;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned NetESignal::lsi() const
|
long NetESignal::lsi() const
|
||||||
{
|
{
|
||||||
return net_->lsb();
|
return net_->lsb();
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned NetESignal::msi() const
|
long NetESignal::msi() const
|
||||||
{
|
{
|
||||||
return net_->msb();
|
return net_->msb();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
34
netlist.h
34
netlist.h
|
|
@ -193,11 +193,17 @@ class NetPins : public LineInfo {
|
||||||
const Link&pin(unsigned idx) const;
|
const Link&pin(unsigned idx) const;
|
||||||
|
|
||||||
void dump_node_pins(ostream&, unsigned, const char**pin_names =0) const;
|
void dump_node_pins(ostream&, unsigned, const char**pin_names =0) const;
|
||||||
|
void set_default_dir(Link::DIR d);
|
||||||
|
void set_default_init(verinum::V val);
|
||||||
bool is_linked();
|
bool is_linked();
|
||||||
|
bool pins_are_virtual(void) const;
|
||||||
|
void devirtualize_pins(void);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Link*pins_;
|
Link*pins_;
|
||||||
const unsigned npins_;
|
const unsigned npins_;
|
||||||
|
Link::DIR default_dir_;
|
||||||
|
verinum::V default_init_;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* =========
|
/* =========
|
||||||
|
|
@ -536,7 +542,7 @@ class NetNet : public NetObj {
|
||||||
public:
|
public:
|
||||||
enum Type { NONE, IMPLICIT, IMPLICIT_REG, INTEGER, WIRE, TRI, TRI1,
|
enum Type { NONE, IMPLICIT, IMPLICIT_REG, INTEGER, WIRE, TRI, TRI1,
|
||||||
SUPPLY0, SUPPLY1, WAND, TRIAND, TRI0, WOR, TRIOR, REG,
|
SUPPLY0, SUPPLY1, WAND, TRIAND, TRI0, WOR, TRIOR, REG,
|
||||||
WONE };
|
UWIRE };
|
||||||
|
|
||||||
enum PortType { NOT_A_PORT, PIMPLICIT, PINPUT, POUTPUT, PINOUT };
|
enum PortType { NOT_A_PORT, PIMPLICIT, PINPUT, POUTPUT, PINOUT };
|
||||||
|
|
||||||
|
|
@ -575,6 +581,9 @@ class NetNet : public NetObj {
|
||||||
bool get_isint() const;
|
bool get_isint() const;
|
||||||
void set_isint(bool);
|
void set_isint(bool);
|
||||||
|
|
||||||
|
bool get_scalar() const;
|
||||||
|
void set_scalar(bool);
|
||||||
|
|
||||||
/* Attach a discipline to the net. */
|
/* Attach a discipline to the net. */
|
||||||
ivl_discipline_t get_discipline() const;
|
ivl_discipline_t get_discipline() const;
|
||||||
void set_discipline(ivl_discipline_t dis);
|
void set_discipline(ivl_discipline_t dis);
|
||||||
|
|
@ -644,6 +653,7 @@ class NetNet : public NetObj {
|
||||||
ivl_variable_type_t data_type_;
|
ivl_variable_type_t data_type_;
|
||||||
bool signed_;
|
bool signed_;
|
||||||
bool isint_; // original type of integer
|
bool isint_; // original type of integer
|
||||||
|
bool is_scalar_;
|
||||||
ivl_discipline_t discipline_;
|
ivl_discipline_t discipline_;
|
||||||
|
|
||||||
long msb_, lsb_;
|
long msb_, lsb_;
|
||||||
|
|
@ -710,6 +720,9 @@ class NetScope : public Attrib {
|
||||||
void rem_event(NetEvent*);
|
void rem_event(NetEvent*);
|
||||||
NetEvent*find_event(perm_string name);
|
NetEvent*find_event(perm_string name);
|
||||||
|
|
||||||
|
/* These methods add or find a genvar that lives in this scope. */
|
||||||
|
void add_genvar(perm_string name, LineInfo *li);
|
||||||
|
LineInfo* find_genvar(perm_string name);
|
||||||
|
|
||||||
/* These methods manage signals. The add_ and rem_signal
|
/* These methods manage signals. The add_ and rem_signal
|
||||||
methods are used by the NetNet objects to make themselves
|
methods are used by the NetNet objects to make themselves
|
||||||
|
|
@ -728,6 +741,7 @@ class NetScope : public Attrib {
|
||||||
const NetScope* child(const hname_t&name) const;
|
const NetScope* child(const hname_t&name) const;
|
||||||
|
|
||||||
TYPE type() const;
|
TYPE type() const;
|
||||||
|
void print_type(ostream&) const;
|
||||||
|
|
||||||
void set_task_def(NetTaskDef*);
|
void set_task_def(NetTaskDef*);
|
||||||
void set_func_def(NetFuncDef*);
|
void set_func_def(NetFuncDef*);
|
||||||
|
|
@ -750,6 +764,10 @@ class NetScope : public Attrib {
|
||||||
void is_auto(bool is_auto__) { is_auto_ = is_auto__; };
|
void is_auto(bool is_auto__) { is_auto_ = is_auto__; };
|
||||||
bool is_auto() const { return is_auto_; };
|
bool is_auto() const { return is_auto_; };
|
||||||
|
|
||||||
|
/* Is the module a cell (is in a `celldefine) */
|
||||||
|
void is_cell(bool is_cell__) { is_cell_ = is_cell__; };
|
||||||
|
bool is_cell() const { return is_cell_; };
|
||||||
|
|
||||||
const NetTaskDef* task_def() const;
|
const NetTaskDef* task_def() const;
|
||||||
const NetFuncDef* func_def() const;
|
const NetFuncDef* func_def() const;
|
||||||
|
|
||||||
|
|
@ -767,9 +785,11 @@ class NetScope : public Attrib {
|
||||||
|
|
||||||
void time_unit(int);
|
void time_unit(int);
|
||||||
void time_precision(int);
|
void time_precision(int);
|
||||||
|
void time_from_timescale(bool);
|
||||||
|
|
||||||
int time_unit() const;
|
int time_unit() const;
|
||||||
int time_precision() const;
|
int time_precision() const;
|
||||||
|
bool time_from_timescale() const;
|
||||||
|
|
||||||
void default_nettype(NetNet::Type);
|
void default_nettype(NetNet::Type);
|
||||||
NetNet::Type default_nettype() const;
|
NetNet::Type default_nettype() const;
|
||||||
|
|
@ -877,10 +897,13 @@ class NetScope : public Attrib {
|
||||||
unsigned def_lineno_;
|
unsigned def_lineno_;
|
||||||
|
|
||||||
signed char time_unit_, time_prec_;
|
signed char time_unit_, time_prec_;
|
||||||
|
bool time_from_timescale_;
|
||||||
NetNet::Type default_nettype_;
|
NetNet::Type default_nettype_;
|
||||||
|
|
||||||
NetEvent *events_;
|
NetEvent *events_;
|
||||||
|
|
||||||
|
map<perm_string,LineInfo*> genvars_;
|
||||||
|
|
||||||
typedef std::map<perm_string,NetNet*>::const_iterator signals_map_iter_t;
|
typedef std::map<perm_string,NetNet*>::const_iterator signals_map_iter_t;
|
||||||
std::map <perm_string,NetNet*> signals_map_;
|
std::map <perm_string,NetNet*> signals_map_;
|
||||||
perm_string module_name_;
|
perm_string module_name_;
|
||||||
|
|
@ -894,7 +917,7 @@ class NetScope : public Attrib {
|
||||||
NetScope*sub_;
|
NetScope*sub_;
|
||||||
|
|
||||||
unsigned lcounter_;
|
unsigned lcounter_;
|
||||||
bool is_auto_;
|
bool is_auto_, is_cell_;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -3256,6 +3279,7 @@ class NetEBAdd : public NetEBinary {
|
||||||
virtual ivl_variable_type_t expr_type() const;
|
virtual ivl_variable_type_t expr_type() const;
|
||||||
|
|
||||||
virtual bool set_width(unsigned w, bool last_chance);
|
virtual bool set_width(unsigned w, bool last_chance);
|
||||||
|
virtual void cast_signed(bool sign_flag);
|
||||||
virtual NetEBAdd* dup_expr() const;
|
virtual NetEBAdd* dup_expr() const;
|
||||||
virtual NetExpr* eval_tree(int prune_to_width = -1);
|
virtual NetExpr* eval_tree(int prune_to_width = -1);
|
||||||
virtual NetNet* synthesize(Design*, NetScope*scope, NetExpr*root);
|
virtual NetNet* synthesize(Design*, NetScope*scope, NetExpr*root);
|
||||||
|
|
@ -3278,6 +3302,7 @@ class NetEBDiv : public NetEBinary {
|
||||||
virtual ivl_variable_type_t expr_type() const;
|
virtual ivl_variable_type_t expr_type() const;
|
||||||
|
|
||||||
virtual bool set_width(unsigned w, bool last_chance);
|
virtual bool set_width(unsigned w, bool last_chance);
|
||||||
|
virtual void cast_signed(bool sign_flag);
|
||||||
virtual NetEBDiv* dup_expr() const;
|
virtual NetEBDiv* dup_expr() const;
|
||||||
virtual NetExpr* eval_tree(int prune_to_width = -1);
|
virtual NetExpr* eval_tree(int prune_to_width = -1);
|
||||||
virtual NetNet* synthesize(Design*, NetScope*scope, NetExpr*root);
|
virtual NetNet* synthesize(Design*, NetScope*scope, NetExpr*root);
|
||||||
|
|
@ -3408,6 +3433,7 @@ class NetEBMult : public NetEBinary {
|
||||||
virtual ivl_variable_type_t expr_type() const;
|
virtual ivl_variable_type_t expr_type() const;
|
||||||
|
|
||||||
virtual bool set_width(unsigned w, bool last_chance);
|
virtual bool set_width(unsigned w, bool last_chance);
|
||||||
|
virtual void cast_signed(bool sign_flag);
|
||||||
virtual NetEBMult* dup_expr() const;
|
virtual NetEBMult* dup_expr() const;
|
||||||
virtual NetExpr* eval_tree(int prune_to_width = -1);
|
virtual NetExpr* eval_tree(int prune_to_width = -1);
|
||||||
virtual NetNet* synthesize(Design*, NetScope*scope, NetExpr*root);
|
virtual NetNet* synthesize(Design*, NetScope*scope, NetExpr*root);
|
||||||
|
|
@ -3803,8 +3829,8 @@ class NetESignal : public NetExpr {
|
||||||
const NetNet* sig() const;
|
const NetNet* sig() const;
|
||||||
NetNet* sig();
|
NetNet* sig();
|
||||||
// Declared vector dimensions for the signal.
|
// Declared vector dimensions for the signal.
|
||||||
unsigned msi() const;
|
long msi() const;
|
||||||
unsigned lsi() const;
|
long lsi() const;
|
||||||
|
|
||||||
virtual ivl_variable_type_t expr_type() const;
|
virtual ivl_variable_type_t expr_type() const;
|
||||||
|
|
||||||
|
|
|
||||||
47
netlist.txt
47
netlist.txt
|
|
@ -16,7 +16,6 @@
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
*/
|
*/
|
||||||
#ident "$Id: netlist.txt,v 1.10 2000/07/23 18:06:15 steve Exp $"
|
|
||||||
|
|
||||||
|
|
||||||
Note that the netlist.h header contains detailed descriptions of how
|
Note that the netlist.h header contains detailed descriptions of how
|
||||||
|
|
@ -291,49 +290,3 @@ values. These are filled in during scope elaboration and are used in
|
||||||
subsequent elaboration phases to arrange for scaling of delays. This
|
subsequent elaboration phases to arrange for scaling of delays. This
|
||||||
information can also be used by the code generator to scale times back
|
information can also be used by the code generator to scale times back
|
||||||
to the units of the scope, if that is desired.
|
to the units of the scope, if that is desired.
|
||||||
|
|
||||||
$Log: netlist.txt,v $
|
|
||||||
Revision 1.10 2000/07/23 18:06:15 steve
|
|
||||||
Document time scale in netlists.
|
|
||||||
|
|
||||||
Revision 1.9 2000/07/14 06:12:57 steve
|
|
||||||
Move inital value handling from NetNet to Nexus
|
|
||||||
objects. This allows better propogation of inital
|
|
||||||
values.
|
|
||||||
|
|
||||||
Clean up constant propagation a bit to account
|
|
||||||
for regs that are not really values.
|
|
||||||
|
|
||||||
Revision 1.8 2000/03/08 04:36:54 steve
|
|
||||||
Redesign the implementation of scopes and parameters.
|
|
||||||
I now generate the scopes and notice the parameters
|
|
||||||
in a separate pass over the pform. Once the scopes
|
|
||||||
are generated, I can process overrides and evalutate
|
|
||||||
paremeters before elaboration begins.
|
|
||||||
|
|
||||||
Revision 1.7 1999/11/28 23:42:02 steve
|
|
||||||
NetESignal object no longer need to be NetNode
|
|
||||||
objects. Let them keep a pointer to NetNet objects.
|
|
||||||
|
|
||||||
Revision 1.6 1999/11/21 00:13:09 steve
|
|
||||||
Support memories in continuous assignments.
|
|
||||||
|
|
||||||
Revision 1.5 1999/11/02 04:55:34 steve
|
|
||||||
Add the synthesize method to NetExpr to handle
|
|
||||||
synthesis of expressions, and use that method
|
|
||||||
to improve r-value handling of LPM_FF synthesis.
|
|
||||||
|
|
||||||
Modify the XNF target to handle LPM_FF objects.
|
|
||||||
|
|
||||||
Revision 1.4 1999/09/29 00:03:27 steve
|
|
||||||
Spelling fixes from Larry.
|
|
||||||
|
|
||||||
Revision 1.3 1999/07/24 02:11:20 steve
|
|
||||||
Elaborate task input ports.
|
|
||||||
|
|
||||||
Revision 1.2 1999/07/21 01:15:29 steve
|
|
||||||
Document netlist semantics.
|
|
||||||
|
|
||||||
Revision 1.1 1999/05/27 04:13:08 steve
|
|
||||||
Handle expression bit widths with non-fatal errors.
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -416,6 +416,7 @@ const char *human_readable_op(const char op, bool unary)
|
||||||
case '-': type = "-"; break;
|
case '-': type = "-"; break;
|
||||||
case '*': type = "*"; break;
|
case '*': type = "*"; break;
|
||||||
case '/': type = "/"; break;
|
case '/': type = "/"; break;
|
||||||
|
case '%': type = "%"; break;
|
||||||
|
|
||||||
case '<': type = "<"; break;
|
case '<': type = "<"; break;
|
||||||
case '>': type = ">"; break;
|
case '>': type = ">"; break;
|
||||||
|
|
|
||||||
|
|
@ -231,4 +231,8 @@ const char *human_readable_op(const char op, bool unary = false);
|
||||||
enum const_bool { C_NON, C_0, C_1, C_X };
|
enum const_bool { C_NON, C_0, C_1, C_X };
|
||||||
const_bool const_logical(const NetExpr*expr);
|
const_bool const_logical(const NetExpr*expr);
|
||||||
|
|
||||||
|
extern bool dly_used_no_timescale;
|
||||||
|
extern bool dly_used_timescale;
|
||||||
|
extern bool display_ts_dly_warning;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
290
parse.y
290
parse.y
|
|
@ -80,6 +80,22 @@ static stack<PBlock*> current_block_stack;
|
||||||
const static struct str_pair_t pull_strength = { PGate::PULL, PGate::PULL };
|
const static struct str_pair_t pull_strength = { PGate::PULL, PGate::PULL };
|
||||||
const static struct str_pair_t str_strength = { PGate::STRONG, PGate::STRONG };
|
const static struct str_pair_t str_strength = { PGate::STRONG, PGate::STRONG };
|
||||||
|
|
||||||
|
static list<pair<perm_string,PExpr*> >* make_port_list(char*id, PExpr*expr)
|
||||||
|
{
|
||||||
|
list<pair<perm_string,PExpr*> >*tmp = new list<pair<perm_string,PExpr*> >;
|
||||||
|
tmp->push_back(make_pair(lex_strings.make(id), expr));
|
||||||
|
delete[]id;
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
static list<pair<perm_string,PExpr*> >* make_port_list(list<pair<perm_string,
|
||||||
|
PExpr*> >*tmp,
|
||||||
|
char*id, PExpr*expr)
|
||||||
|
{
|
||||||
|
tmp->push_back(make_pair(lex_strings.make(id), expr));
|
||||||
|
delete[]id;
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
static list<perm_string>* list_from_identifier(char*id)
|
static list<perm_string>* list_from_identifier(char*id)
|
||||||
{
|
{
|
||||||
list<perm_string>*tmp = new list<perm_string>;
|
list<perm_string>*tmp = new list<perm_string>;
|
||||||
|
|
@ -146,6 +162,9 @@ static PECallFunction*make_call_function(perm_string tn, PExpr*arg1, PExpr*arg2)
|
||||||
strdup. They can be put into lists with the texts type. */
|
strdup. They can be put into lists with the texts type. */
|
||||||
char*text;
|
char*text;
|
||||||
list<perm_string>*perm_strings;
|
list<perm_string>*perm_strings;
|
||||||
|
|
||||||
|
list<pair<perm_string,PExpr*> >*port_list;
|
||||||
|
|
||||||
pform_name_t*pform_name;
|
pform_name_t*pform_name;
|
||||||
|
|
||||||
ivl_discipline_t discipline;
|
ivl_discipline_t discipline;
|
||||||
|
|
@ -210,40 +229,56 @@ static PECallFunction*make_call_function(perm_string tn, PExpr*arg1, PExpr*arg2)
|
||||||
%token K_PO_POS K_PO_NEG K_POW
|
%token K_PO_POS K_PO_NEG K_POW
|
||||||
%token K_PSTAR K_STARP
|
%token K_PSTAR K_STARP
|
||||||
%token K_LOR K_LAND K_NAND K_NOR K_NXOR K_TRIGGER
|
%token K_LOR K_LAND K_NAND K_NOR K_NXOR K_TRIGGER
|
||||||
%token K_abs K_abstol K_access K_acos K_acosh K_asin K_analog K_asinh
|
%token K_edge_descriptor
|
||||||
%token K_atan K_atanh K_atan2 K_automatic
|
|
||||||
%token K_always K_and K_assign K_begin K_bool K_buf K_bufif0 K_bufif1 K_case
|
|
||||||
%token K_casex K_casez K_ceil K_cmos K_continuous K_cos K_cosh
|
|
||||||
%token K_ddt_nature K_deassign K_default K_defparam K_disable K_discrete
|
|
||||||
%token K_domain K_edge K_edge_descriptor K_discipline
|
|
||||||
%token K_else K_end K_endcase K_enddiscipline K_endfunction K_endgenerate
|
|
||||||
%token K_endmodule K_endnature
|
|
||||||
%token K_endprimitive K_endspecify K_endtable K_endtask K_event
|
|
||||||
%token K_exclude K_exp K_floor K_flow K_from
|
|
||||||
%token K_for K_force K_forever K_fork K_function K_generate K_genvar
|
|
||||||
%token K_ground K_highz0 K_highz1 K_hypot K_idt_nature K_if K_ifnone K_inf
|
|
||||||
%token K_initial K_inout K_input K_integer K_join K_large K_ln K_localparam
|
|
||||||
%token K_log K_logic K_macromodule K_max
|
|
||||||
%token K_medium K_min K_module K_nand K_nature K_negedge
|
|
||||||
%token K_nmos K_nor K_not K_notif0
|
|
||||||
%token K_notif1 K_or K_output K_parameter K_pmos K_posedge K_potential
|
|
||||||
%token K_pow K_primitive
|
|
||||||
%token K_pull0 K_pull1 K_pulldown K_pullup K_rcmos K_real K_realtime
|
|
||||||
%token K_reg K_release K_repeat
|
|
||||||
%token K_rnmos K_rpmos K_rtran K_rtranif0 K_rtranif1 K_scalared
|
|
||||||
%token K_signed K_sin K_sinh K_small K_specify
|
|
||||||
%token K_specparam K_sqrt K_string K_strong0 K_strong1 K_supply0 K_supply1
|
|
||||||
%token K_table
|
|
||||||
%token K_tan K_tanh K_task
|
|
||||||
%token K_time K_tran K_tranif0 K_tranif1 K_tri K_tri0 K_tri1 K_triand
|
|
||||||
%token K_trior K_trireg K_units K_vectored K_wait K_wand K_weak0 K_weak1
|
|
||||||
%token K_while K_wire
|
|
||||||
%token K_wone K_wor K_xnor K_xor
|
|
||||||
%token K_Shold K_Speriod K_Srecovery K_Srecrem K_Ssetup K_Swidth K_Ssetuphold
|
|
||||||
|
|
||||||
|
/* The base tokens from 1364-1995. */
|
||||||
|
%token K_always K_and K_assign K_begin K_buf K_bufif0 K_bufif1 K_case
|
||||||
|
%token K_casex K_casez K_cmos K_deassign K_default K_defparam K_disable
|
||||||
|
%token K_edge K_else K_end K_endcase K_endfunction 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_highz0 K_highz1 K_if
|
||||||
|
%token K_ifnone K_initial K_inout K_input K_integer K_join K_large
|
||||||
|
%token K_macromodule K_medium K_module K_nand K_negedge K_nmos K_nor
|
||||||
|
%token K_not K_notif0 K_notif1 K_or K_output K_parameter K_pmos K_posedge
|
||||||
|
%token K_primitive K_pull0 K_pull1 K_pulldown K_pullup K_rcmos K_real
|
||||||
|
%token K_realtime K_reg K_release K_repeat K_rnmos K_rpmos K_rtran
|
||||||
|
%token K_rtranif0 K_rtranif1 K_scalared K_small K_specify K_specparam
|
||||||
|
%token K_strong0 K_strong1 K_supply0 K_supply1 K_table K_task K_time
|
||||||
|
%token K_tran K_tranif0 K_tranif1 K_tri K_tri0 K_tri1 K_triand K_trior
|
||||||
|
%token K_trireg K_vectored K_wait K_wand K_weak0 K_weak1 K_while K_wire
|
||||||
|
%token K_wor K_xnor K_xor
|
||||||
|
|
||||||
|
%token K_Shold K_Snochange K_Speriod K_Srecovery K_Ssetup K_Ssetuphold
|
||||||
|
%token K_Sskew K_Swidth
|
||||||
|
|
||||||
|
/* Icarus specific tokens. */
|
||||||
|
%token KK_attribute K_bool K_logic
|
||||||
|
|
||||||
|
/* The new tokens from 1364-2001. */
|
||||||
|
%token K_automatic K_endgenerate K_generate K_genvar K_localparam
|
||||||
|
%token K_noshowcancelled K_pulsestyle_onevent K_pulsestyle_ondetect
|
||||||
|
%token K_showcancelled K_signed K_unsigned
|
||||||
|
|
||||||
|
%token K_Sfullskew K_Srecrem K_Sremoval K_Stimeskew
|
||||||
|
|
||||||
|
/* The 1364-2001 configuration tokens. */
|
||||||
|
%token K_cell K_config K_design K_endconfig K_incdir K_include K_instance
|
||||||
|
%token K_liblist K_library K_use
|
||||||
|
|
||||||
|
/* The new tokens from 1364-2005. */
|
||||||
|
%token K_wone K_uwire
|
||||||
|
|
||||||
|
/* The new tokens from 1800-2005. */
|
||||||
%token K_always_comb K_always_ff K_always_latch K_assert
|
%token K_always_comb K_always_ff K_always_latch K_assert
|
||||||
|
|
||||||
%token KK_attribute
|
/* The new tokens for Verilog-AMS 2.3. */
|
||||||
|
%token K_abs K_abstol K_access K_acos K_acosh K_analog K_asin K_asinh
|
||||||
|
%token K_atan K_atan2 K_atanh K_ceil K_continuous K_cos K_cosh
|
||||||
|
%token K_ddt_nature K_discipline K_discrete K_domain K_enddiscipline
|
||||||
|
%token K_endnature K_exclude K_exp K_floor K_flow K_from K_ground
|
||||||
|
%token K_hypot K_idt_nature K_inf K_ln K_log K_max K_min K_nature
|
||||||
|
%token K_potential K_pow K_sin K_sinh K_sqrt K_string K_tan K_tanh
|
||||||
|
%token K_units
|
||||||
|
|
||||||
%type <flag> from_exclude
|
%type <flag> from_exclude
|
||||||
%type <number> number
|
%type <number> number
|
||||||
|
|
@ -260,7 +295,9 @@ static PECallFunction*make_call_function(perm_string tn, PExpr*arg1, PExpr*arg2)
|
||||||
%type <expr> udp_initial_expr_opt
|
%type <expr> udp_initial_expr_opt
|
||||||
|
|
||||||
%type <text> register_variable net_variable real_variable
|
%type <text> register_variable net_variable real_variable
|
||||||
%type <perm_strings> register_variable_list net_variable_list real_variable_list list_of_identifiers
|
%type <perm_strings> register_variable_list net_variable_list
|
||||||
|
%type <perm_strings> real_variable_list list_of_identifiers
|
||||||
|
%type <port_list> list_of_port_identifiers
|
||||||
|
|
||||||
%type <net_decl_assign> net_decl_assign net_decl_assigns
|
%type <net_decl_assign> net_decl_assign net_decl_assigns
|
||||||
|
|
||||||
|
|
@ -682,6 +719,7 @@ delay_value_simple
|
||||||
description
|
description
|
||||||
: module
|
: module
|
||||||
| udp_primitive
|
| udp_primitive
|
||||||
|
| config_declaration
|
||||||
| nature_declaration
|
| nature_declaration
|
||||||
| discipline_declaration
|
| discipline_declaration
|
||||||
| KK_attribute '(' IDENTIFIER ',' STRING ',' STRING ')'
|
| KK_attribute '(' IDENTIFIER ',' STRING ',' STRING ')'
|
||||||
|
|
@ -746,6 +784,54 @@ nature_item
|
||||||
{ delete[] $3; }
|
{ delete[] $3; }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
config_declaration
|
||||||
|
: K_config IDENTIFIER ';'
|
||||||
|
K_design lib_cell_identifiers ';'
|
||||||
|
list_of_config_rule_statements
|
||||||
|
K_endconfig
|
||||||
|
{ cerr << @1 << ": sorry: config declarations are not supported and "
|
||||||
|
"will be skipped." << endl;
|
||||||
|
delete[] $2;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
lib_cell_identifiers
|
||||||
|
: /* The BNF implies this can be blank, but I'm not sure exactly what
|
||||||
|
* this means. */
|
||||||
|
| lib_cell_identifiers lib_cell_id
|
||||||
|
;
|
||||||
|
|
||||||
|
list_of_config_rule_statements
|
||||||
|
: /* config rules are optional. */
|
||||||
|
| list_of_config_rule_statements config_rule_statement
|
||||||
|
;
|
||||||
|
|
||||||
|
config_rule_statement
|
||||||
|
: K_default K_liblist list_of_libraries ';'
|
||||||
|
| K_instance hierarchy_identifier K_liblist list_of_libraries ';'
|
||||||
|
{ delete $2; }
|
||||||
|
| K_instance hierarchy_identifier K_use lib_cell_id opt_config ';'
|
||||||
|
{ delete $2; }
|
||||||
|
| K_cell lib_cell_id K_liblist list_of_libraries ';'
|
||||||
|
| K_cell lib_cell_id K_use lib_cell_id opt_config ';'
|
||||||
|
;
|
||||||
|
|
||||||
|
opt_config
|
||||||
|
: /* The use clause takse an optional :config. */
|
||||||
|
| ':' K_config
|
||||||
|
|
||||||
|
lib_cell_id
|
||||||
|
: IDENTIFIER
|
||||||
|
{ delete[] $1; }
|
||||||
|
| IDENTIFIER '.' IDENTIFIER
|
||||||
|
{ delete[] $1; delete[] $3; }
|
||||||
|
;
|
||||||
|
|
||||||
|
list_of_libraries
|
||||||
|
: /* A NULL library means use the parents cell library. */
|
||||||
|
| list_of_libraries IDENTIFIER
|
||||||
|
{ delete[] $2; }
|
||||||
|
|
||||||
drive_strength
|
drive_strength
|
||||||
: '(' dr_strength0 ',' dr_strength1 ')'
|
: '(' dr_strength0 ',' dr_strength1 ')'
|
||||||
{ $$.str0 = $2.str0;
|
{ $$.str0 = $2.str0;
|
||||||
|
|
@ -900,6 +986,21 @@ expression
|
||||||
FILE_NAME(tmp, @2);
|
FILE_NAME(tmp, @2);
|
||||||
$$ = tmp;
|
$$ = tmp;
|
||||||
}
|
}
|
||||||
|
| '~' '&' expr_primary %prec UNARY_PREC
|
||||||
|
{ yyerror(@1, "error: '~' '&' is not a valid expression. "
|
||||||
|
"Please use operator '~&' instead.");
|
||||||
|
$$ = 0;
|
||||||
|
}
|
||||||
|
| '~' '|' expr_primary %prec UNARY_PREC
|
||||||
|
{ yyerror(@1, "error: '~' '|' is not a valid expression. "
|
||||||
|
"Please use operator '~|' instead.");
|
||||||
|
$$ = 0;
|
||||||
|
}
|
||||||
|
| '~' '^' expr_primary %prec UNARY_PREC
|
||||||
|
{ yyerror(@1, "error: '~' '^' is not a valid expression. "
|
||||||
|
"Please use operator '~^' instead.");
|
||||||
|
$$ = 0;
|
||||||
|
}
|
||||||
| K_NAND expr_primary %prec UNARY_PREC
|
| K_NAND expr_primary %prec UNARY_PREC
|
||||||
{ PEUnary*tmp = new PEUnary('A', $2);
|
{ PEUnary*tmp = new PEUnary('A', $2);
|
||||||
FILE_NAME(tmp, @2);
|
FILE_NAME(tmp, @2);
|
||||||
|
|
@ -1647,6 +1748,17 @@ list_of_identifiers
|
||||||
{ $$ = list_from_identifier($1, $3); }
|
{ $$ = list_from_identifier($1, $3); }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
list_of_port_identifiers
|
||||||
|
: IDENTIFIER
|
||||||
|
{ $$ = make_port_list($1, 0); }
|
||||||
|
| IDENTIFIER '=' expression
|
||||||
|
{ $$ = make_port_list($1, $3); }
|
||||||
|
| list_of_port_identifiers ',' IDENTIFIER
|
||||||
|
{ $$ = make_port_list($1, $3, 0); }
|
||||||
|
| list_of_port_identifiers ',' IDENTIFIER '=' expression
|
||||||
|
{ $$ = make_port_list($1, $3, $5); }
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
/* The list_of_ports and list_of_port_declarations rules are the
|
/* The list_of_ports and list_of_port_declarations rules are the
|
||||||
port list formats for module ports. The list_of_ports_opt rule is
|
port list formats for module ports. The list_of_ports_opt rule is
|
||||||
|
|
@ -1876,7 +1988,20 @@ module : attribute_list_opt module_start IDENTIFIER
|
||||||
{ pform_module_set_ports($6); }
|
{ pform_module_set_ports($6); }
|
||||||
module_item_list_opt
|
module_item_list_opt
|
||||||
K_endmodule
|
K_endmodule
|
||||||
{ pform_endmodule($3);
|
{ Module::UCDriveType ucd;
|
||||||
|
switch (uc_drive) {
|
||||||
|
case UCD_NONE:
|
||||||
|
default:
|
||||||
|
ucd = Module::UCD_NONE;
|
||||||
|
break;
|
||||||
|
case UCD_PULL0:
|
||||||
|
ucd = Module::UCD_PULL0;
|
||||||
|
break;
|
||||||
|
case UCD_PULL1:
|
||||||
|
ucd = Module::UCD_PULL1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pform_endmodule($3, in_celldefine, ucd);
|
||||||
delete[]$3;
|
delete[]$3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1991,9 +2116,20 @@ module_item
|
||||||
SR_BOTH);
|
SR_BOTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
| K_output var_type signed_opt range_opt list_of_identifiers ';'
|
| K_output var_type signed_opt range_opt list_of_port_identifiers ';'
|
||||||
{ pform_makewire(@1, $4, $3, $5, $2, NetNet::POUTPUT,
|
{ list<pair<perm_string,PExpr*> >::const_iterator pp;
|
||||||
IVL_VT_NO_TYPE, 0, SR_BOTH);
|
list<perm_string>*tmp = new list<perm_string>;
|
||||||
|
for (pp = $5->begin(); pp != $5->end(); pp++) {
|
||||||
|
tmp->push_back((*pp).first);
|
||||||
|
}
|
||||||
|
pform_makewire(@1, $4, $3, tmp, $2, NetNet::POUTPUT,
|
||||||
|
IVL_VT_NO_TYPE, 0, SR_BOTH);
|
||||||
|
for (pp = $5->begin(); pp != $5->end(); pp++) {
|
||||||
|
if ((*pp).second) {
|
||||||
|
pform_make_reginit(@1, (*pp).first, (*pp).second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete $5;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* var_type declaration (reg variables) cannot be input or output,
|
/* var_type declaration (reg variables) cannot be input or output,
|
||||||
|
|
@ -2124,8 +2260,7 @@ module_item
|
||||||
|
|
||||||
| K_task automatic_opt IDENTIFIER ';'
|
| K_task automatic_opt IDENTIFIER ';'
|
||||||
{ assert(current_task == 0);
|
{ assert(current_task == 0);
|
||||||
current_task = pform_push_task_scope($3, $2);
|
current_task = pform_push_task_scope(@1, $3, $2);
|
||||||
FILE_NAME(current_task, @1);
|
|
||||||
}
|
}
|
||||||
task_item_list_opt
|
task_item_list_opt
|
||||||
statement_or_null
|
statement_or_null
|
||||||
|
|
@ -2137,12 +2272,11 @@ module_item
|
||||||
delete[]$3;
|
delete[]$3;
|
||||||
}
|
}
|
||||||
|
|
||||||
| K_task automatic_opt IDENTIFIER
|
| K_task automatic_opt IDENTIFIER '('
|
||||||
{ assert(current_task == 0);
|
{ assert(current_task == 0);
|
||||||
current_task = pform_push_task_scope($3, $2);
|
current_task = pform_push_task_scope(@1, $3, $2);
|
||||||
FILE_NAME(current_task, @1);
|
|
||||||
}
|
}
|
||||||
'(' task_port_decl_list ')' ';'
|
task_port_decl_list ')' ';'
|
||||||
block_item_decls_opt
|
block_item_decls_opt
|
||||||
statement_or_null
|
statement_or_null
|
||||||
K_endtask
|
K_endtask
|
||||||
|
|
@ -2152,6 +2286,23 @@ module_item
|
||||||
current_task = 0;
|
current_task = 0;
|
||||||
delete[]$3;
|
delete[]$3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
| K_task automatic_opt IDENTIFIER '(' ')' ';'
|
||||||
|
{ assert(current_task == 0);
|
||||||
|
current_task = pform_push_task_scope(@1, $3, $2);
|
||||||
|
}
|
||||||
|
block_item_decls_opt
|
||||||
|
statement_or_null
|
||||||
|
K_endtask
|
||||||
|
{ current_task->set_ports(0);
|
||||||
|
current_task->set_statement($9);
|
||||||
|
pform_pop_scope();
|
||||||
|
current_task = 0;
|
||||||
|
cerr << @3 << ": warning: task definition for \"" << $3
|
||||||
|
<< "\" has an empty port declaration list!" << endl;
|
||||||
|
delete[]$3;
|
||||||
|
}
|
||||||
|
|
||||||
| K_task automatic_opt IDENTIFIER error K_endtask
|
| K_task automatic_opt IDENTIFIER error K_endtask
|
||||||
{
|
{
|
||||||
pform_pop_scope();
|
pform_pop_scope();
|
||||||
|
|
@ -2166,8 +2317,7 @@ module_item
|
||||||
|
|
||||||
| K_function automatic_opt function_range_or_type_opt IDENTIFIER ';'
|
| K_function automatic_opt function_range_or_type_opt IDENTIFIER ';'
|
||||||
{ assert(current_function == 0);
|
{ assert(current_function == 0);
|
||||||
current_function = pform_push_function_scope($4, $2);
|
current_function = pform_push_function_scope(@1, $4, $2);
|
||||||
FILE_NAME(current_function, @1);
|
|
||||||
}
|
}
|
||||||
function_item_list statement
|
function_item_list statement
|
||||||
K_endfunction
|
K_endfunction
|
||||||
|
|
@ -2181,8 +2331,7 @@ module_item
|
||||||
|
|
||||||
| K_function automatic_opt function_range_or_type_opt IDENTIFIER
|
| K_function automatic_opt function_range_or_type_opt IDENTIFIER
|
||||||
{ assert(current_function == 0);
|
{ assert(current_function == 0);
|
||||||
current_function = pform_push_function_scope($4, $2);
|
current_function = pform_push_function_scope(@1, $4, $2);
|
||||||
FILE_NAME(current_function, @1);
|
|
||||||
}
|
}
|
||||||
'(' task_port_decl_list ')' ';'
|
'(' task_port_decl_list ')' ';'
|
||||||
block_item_decls_opt
|
block_item_decls_opt
|
||||||
|
|
@ -2244,7 +2393,7 @@ module_item
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
| K_generate K_begin ':' IDENTIFIER {
|
| K_generate K_begin ':' IDENTIFIER {
|
||||||
pform_start_generate_nblock(@1, $4);
|
pform_start_generate_nblock(@2, $4);
|
||||||
} module_item_list_opt K_end K_endgenerate
|
} module_item_list_opt K_end K_endgenerate
|
||||||
{ /* Detect and warn about anachronistic named begin/end use */
|
{ /* Detect and warn about anachronistic named begin/end use */
|
||||||
if (generation_flag > GN_VER2001) {
|
if (generation_flag > GN_VER2001) {
|
||||||
|
|
@ -2410,7 +2559,12 @@ net_type
|
||||||
| K_supply1 { $$ = NetNet::SUPPLY1; }
|
| K_supply1 { $$ = NetNet::SUPPLY1; }
|
||||||
| K_wor { $$ = NetNet::WOR; }
|
| K_wor { $$ = NetNet::WOR; }
|
||||||
| K_trior { $$ = NetNet::TRIOR; }
|
| K_trior { $$ = NetNet::TRIOR; }
|
||||||
| K_wone { $$ = NetNet::WONE; }
|
| K_wone { $$ = NetNet::UWIRE;
|
||||||
|
cerr << @1.text << ":" << @1.first_line << ": warning: "
|
||||||
|
"'wone' is deprecated, please use 'uwire' "
|
||||||
|
"instead." << endl;
|
||||||
|
}
|
||||||
|
| K_uwire { $$ = NetNet::UWIRE; }
|
||||||
;
|
;
|
||||||
|
|
||||||
var_type
|
var_type
|
||||||
|
|
@ -3095,10 +3249,20 @@ specify_item
|
||||||
}
|
}
|
||||||
pform_module_specify_path(tmp);
|
pform_module_specify_path(tmp);
|
||||||
}
|
}
|
||||||
|
| K_Sfullskew '(' spec_reference_event ',' spec_reference_event
|
||||||
|
',' delay_value ',' delay_value spec_notifier_opt ')' ';'
|
||||||
|
{ delete $7;
|
||||||
|
delete $9;
|
||||||
|
}
|
||||||
| K_Shold '(' spec_reference_event ',' spec_reference_event
|
| K_Shold '(' spec_reference_event ',' spec_reference_event
|
||||||
',' delay_value spec_notifier_opt ')' ';'
|
',' delay_value spec_notifier_opt ')' ';'
|
||||||
{ delete $7;
|
{ delete $7;
|
||||||
}
|
}
|
||||||
|
| K_Snochange '(' spec_reference_event ',' spec_reference_event
|
||||||
|
',' delay_value ',' delay_value spec_notifier_opt ')' ';'
|
||||||
|
{ delete $7;
|
||||||
|
delete $9;
|
||||||
|
}
|
||||||
| K_Speriod '(' spec_reference_event ',' delay_value
|
| K_Speriod '(' spec_reference_event ',' delay_value
|
||||||
spec_notifier_opt ')' ';'
|
spec_notifier_opt ')' ';'
|
||||||
{ delete $5;
|
{ delete $5;
|
||||||
|
|
@ -3107,6 +3271,15 @@ specify_item
|
||||||
',' delay_value spec_notifier_opt ')' ';'
|
',' delay_value spec_notifier_opt ')' ';'
|
||||||
{ delete $7;
|
{ delete $7;
|
||||||
}
|
}
|
||||||
|
| K_Srecrem '(' spec_reference_event ',' spec_reference_event
|
||||||
|
',' delay_value ',' delay_value spec_notifier_opt ')' ';'
|
||||||
|
{ delete $7;
|
||||||
|
delete $9;
|
||||||
|
}
|
||||||
|
| K_Sremoval '(' spec_reference_event ',' spec_reference_event
|
||||||
|
',' delay_value spec_notifier_opt ')' ';'
|
||||||
|
{ delete $7;
|
||||||
|
}
|
||||||
| K_Ssetup '(' spec_reference_event ',' spec_reference_event
|
| K_Ssetup '(' spec_reference_event ',' spec_reference_event
|
||||||
',' delay_value spec_notifier_opt ')' ';'
|
',' delay_value spec_notifier_opt ')' ';'
|
||||||
{ delete $7;
|
{ delete $7;
|
||||||
|
|
@ -3116,10 +3289,13 @@ specify_item
|
||||||
{ delete $7;
|
{ delete $7;
|
||||||
delete $9;
|
delete $9;
|
||||||
}
|
}
|
||||||
| K_Srecrem '(' spec_reference_event ',' spec_reference_event
|
| K_Sskew '(' spec_reference_event ',' spec_reference_event
|
||||||
',' delay_value ',' delay_value spec_notifier_opt ')' ';'
|
',' delay_value spec_notifier_opt ')' ';'
|
||||||
|
{ delete $7;
|
||||||
|
}
|
||||||
|
| K_Stimeskew '(' spec_reference_event ',' spec_reference_event
|
||||||
|
',' delay_value spec_notifier_opt ')' ';'
|
||||||
{ delete $7;
|
{ delete $7;
|
||||||
delete $9;
|
|
||||||
}
|
}
|
||||||
| K_Swidth '(' spec_reference_event ',' delay_value ',' expression
|
| K_Swidth '(' spec_reference_event ',' delay_value ',' expression
|
||||||
spec_notifier_opt ')' ';'
|
spec_notifier_opt ')' ';'
|
||||||
|
|
@ -3129,6 +3305,18 @@ specify_item
|
||||||
| K_Swidth '(' spec_reference_event ',' delay_value ')' ';'
|
| K_Swidth '(' spec_reference_event ',' delay_value ')' ';'
|
||||||
{ delete $5;
|
{ delete $5;
|
||||||
}
|
}
|
||||||
|
| K_pulsestyle_onevent specify_path_identifiers ';'
|
||||||
|
{ delete $2;
|
||||||
|
}
|
||||||
|
| K_pulsestyle_ondetect specify_path_identifiers ';'
|
||||||
|
{ delete $2;
|
||||||
|
}
|
||||||
|
| K_showcancelled specify_path_identifiers ';'
|
||||||
|
{ delete $2;
|
||||||
|
}
|
||||||
|
| K_noshowcancelled specify_path_identifiers ';'
|
||||||
|
{ delete $2;
|
||||||
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
specify_item_list
|
specify_item_list
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef __parse_api_H
|
#ifndef __parse_api_H
|
||||||
#define __parse_api_H
|
#define __parse_api_H
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2001-2009 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -46,4 +46,9 @@ extern int pform_parse(const char*path, FILE*file =0);
|
||||||
|
|
||||||
extern string vl_file;
|
extern string vl_file;
|
||||||
|
|
||||||
|
extern void pform_set_timescale(int units, int prec, const char*file,
|
||||||
|
unsigned lineno);
|
||||||
|
extern int def_ts_units;
|
||||||
|
extern int def_ts_prec;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef __parse_misc_H
|
#ifndef __parse_misc_H
|
||||||
#define __parse_misc_H
|
#define __parse_misc_H
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1998-2000 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 1998-2009 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -60,9 +60,15 @@ extern void VLerror(const YYLTYPE&loc, const char*msg);
|
||||||
#define yywarn VLwarn
|
#define yywarn VLwarn
|
||||||
extern void VLwarn(const YYLTYPE&loc, const char*msg);
|
extern void VLwarn(const YYLTYPE&loc, const char*msg);
|
||||||
|
|
||||||
|
extern void destroy_lexor();
|
||||||
|
|
||||||
extern ostream& operator << (ostream&, const YYLTYPE&loc);
|
extern ostream& operator << (ostream&, const YYLTYPE&loc);
|
||||||
|
|
||||||
extern unsigned error_count, warn_count;
|
extern unsigned error_count, warn_count;
|
||||||
extern unsigned long based_size;
|
extern unsigned long based_size;
|
||||||
|
|
||||||
|
extern bool in_celldefine;
|
||||||
|
enum UCDriveType { UCD_NONE, UCD_PULL0, UCD_PULL1 };
|
||||||
|
extern UCDriveType uc_drive;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
195
pform.cc
195
pform.cc
|
|
@ -70,11 +70,11 @@ static NetNet::Type pform_default_nettype = NetNet::WIRE;
|
||||||
* These variables track the current time scale, as well as where the
|
* These variables track the current time scale, as well as where the
|
||||||
* timescale was set. This supports warnings about tangled timescales.
|
* timescale was set. This supports warnings about tangled timescales.
|
||||||
*/
|
*/
|
||||||
static int pform_time_unit = 0;
|
static int pform_time_unit;
|
||||||
static int pform_time_prec = 0;
|
static int pform_time_prec;
|
||||||
|
|
||||||
static char*pform_timescale_file = 0;
|
static char*pform_timescale_file = 0;
|
||||||
static unsigned pform_timescale_line = 0;
|
static unsigned pform_timescale_line;
|
||||||
|
|
||||||
static inline void FILE_NAME(LineInfo*obj, const char*file, unsigned lineno)
|
static inline void FILE_NAME(LineInfo*obj, const char*file, unsigned lineno)
|
||||||
{
|
{
|
||||||
|
|
@ -103,7 +103,7 @@ void pform_pop_scope()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PTask* pform_push_task_scope(char*name, bool is_auto)
|
PTask* pform_push_task_scope(const struct vlltype&loc, char*name, bool is_auto)
|
||||||
{
|
{
|
||||||
perm_string task_name = lex_strings.make(name);
|
perm_string task_name = lex_strings.make(name);
|
||||||
|
|
||||||
|
|
@ -111,11 +111,30 @@ PTask* pform_push_task_scope(char*name, bool is_auto)
|
||||||
if (pform_cur_generate) {
|
if (pform_cur_generate) {
|
||||||
task = new PTask(task_name, pform_cur_generate->lexical_scope,
|
task = new PTask(task_name, pform_cur_generate->lexical_scope,
|
||||||
is_auto);
|
is_auto);
|
||||||
|
FILE_NAME(task, loc);
|
||||||
|
// Check if the task is already in the dictionary.
|
||||||
|
if (pform_cur_generate->tasks.find(task->pscope_name()) !=
|
||||||
|
pform_cur_generate->tasks.end()) {
|
||||||
|
cerr << task->get_fileline() << ": error: duplicate "
|
||||||
|
"definition for task '" << name << "' in '"
|
||||||
|
<< pform_cur_module->mod_name() << "' (generate)."
|
||||||
|
<< endl;
|
||||||
|
error_count += 1;
|
||||||
|
}
|
||||||
pform_cur_generate->tasks[task->pscope_name()] = task;
|
pform_cur_generate->tasks[task->pscope_name()] = task;
|
||||||
pform_cur_generate->lexical_scope = task;
|
pform_cur_generate->lexical_scope = task;
|
||||||
} else {
|
} else {
|
||||||
task = new PTask(task_name, lexical_scope,
|
task = new PTask(task_name, lexical_scope,
|
||||||
is_auto);
|
is_auto);
|
||||||
|
FILE_NAME(task, loc);
|
||||||
|
// Check if the task is already in the dictionary.
|
||||||
|
if (pform_cur_module->tasks.find(task->pscope_name()) !=
|
||||||
|
pform_cur_module->tasks.end()) {
|
||||||
|
cerr << task->get_fileline() << ": error: duplicate "
|
||||||
|
"definition for task '" << name << "' in '"
|
||||||
|
<< pform_cur_module->mod_name() << "'." << endl;
|
||||||
|
error_count += 1;
|
||||||
|
}
|
||||||
pform_cur_module->tasks[task->pscope_name()] = task;
|
pform_cur_module->tasks[task->pscope_name()] = task;
|
||||||
lexical_scope = task;
|
lexical_scope = task;
|
||||||
}
|
}
|
||||||
|
|
@ -123,7 +142,8 @@ PTask* pform_push_task_scope(char*name, bool is_auto)
|
||||||
return task;
|
return task;
|
||||||
}
|
}
|
||||||
|
|
||||||
PFunction* pform_push_function_scope(char*name, bool is_auto)
|
PFunction* pform_push_function_scope(const struct vlltype&loc, char*name,
|
||||||
|
bool is_auto)
|
||||||
{
|
{
|
||||||
perm_string func_name = lex_strings.make(name);
|
perm_string func_name = lex_strings.make(name);
|
||||||
|
|
||||||
|
|
@ -131,11 +151,30 @@ PFunction* pform_push_function_scope(char*name, bool is_auto)
|
||||||
if (pform_cur_generate) {
|
if (pform_cur_generate) {
|
||||||
func = new PFunction(func_name, pform_cur_generate->lexical_scope,
|
func = new PFunction(func_name, pform_cur_generate->lexical_scope,
|
||||||
is_auto);
|
is_auto);
|
||||||
|
FILE_NAME(func, loc);
|
||||||
|
// Check if the function is already in the dictionary.
|
||||||
|
if (pform_cur_generate->funcs.find(func->pscope_name()) !=
|
||||||
|
pform_cur_generate->funcs.end()) {
|
||||||
|
cerr << func->get_fileline() << ": error: duplicate "
|
||||||
|
"definition for function '" << name << "' in '"
|
||||||
|
<< pform_cur_module->mod_name() << "' (generate)."
|
||||||
|
<< endl;
|
||||||
|
error_count += 1;
|
||||||
|
}
|
||||||
pform_cur_generate->funcs[func->pscope_name()] = func;
|
pform_cur_generate->funcs[func->pscope_name()] = func;
|
||||||
pform_cur_generate->lexical_scope = func;
|
pform_cur_generate->lexical_scope = func;
|
||||||
} else {
|
} else {
|
||||||
func = new PFunction(func_name, lexical_scope,
|
func = new PFunction(func_name, lexical_scope,
|
||||||
is_auto);
|
is_auto);
|
||||||
|
FILE_NAME(func, loc);
|
||||||
|
// Check if the function is already in the dictionary.
|
||||||
|
if (pform_cur_module->funcs.find(func->pscope_name()) !=
|
||||||
|
pform_cur_module->funcs.end()) {
|
||||||
|
cerr << func->get_fileline() << ": error: duplicate "
|
||||||
|
"definition for function '" << name << "' in '"
|
||||||
|
<< pform_cur_module->mod_name() << "'." << endl;
|
||||||
|
error_count += 1;
|
||||||
|
}
|
||||||
pform_cur_module->funcs[func->pscope_name()] = func;
|
pform_cur_module->funcs[func->pscope_name()] = func;
|
||||||
lexical_scope = func;
|
lexical_scope = func;
|
||||||
}
|
}
|
||||||
|
|
@ -259,10 +298,25 @@ void pform_set_timescale(int unit, int prec,
|
||||||
first_flag = false;
|
first_flag = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
pform_timescale_file = strdup(file);
|
if (file) pform_timescale_file = strdup(file);
|
||||||
|
else pform_timescale_file = 0;
|
||||||
pform_timescale_line = lineno;
|
pform_timescale_line = lineno;
|
||||||
|
|
||||||
if (warn_timescale && first_flag && (pform_modules.size() > 0)) {
|
if (!warn_timescale || !first_flag || !file) return;
|
||||||
|
|
||||||
|
/* Look to see if we have any modules without a timescale. */
|
||||||
|
bool have_no_ts = false;
|
||||||
|
map<perm_string,Module*>::iterator mod;
|
||||||
|
for (mod = pform_modules.begin(); mod != pform_modules.end(); mod++) {
|
||||||
|
const Module*mp = (*mod).second;
|
||||||
|
if (mp->time_from_timescale ||
|
||||||
|
mp->timescale_warn_done) continue;
|
||||||
|
have_no_ts = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we do then print a message for the new ones. */
|
||||||
|
if (have_no_ts) {
|
||||||
cerr << file << ":" << lineno << ": warning: "
|
cerr << file << ":" << lineno << ": warning: "
|
||||||
<< "Some modules have no timescale. This may cause"
|
<< "Some modules have no timescale. This may cause"
|
||||||
<< endl;
|
<< endl;
|
||||||
|
|
@ -273,7 +327,10 @@ void pform_set_timescale(int unit, int prec,
|
||||||
map<perm_string,Module*>::iterator mod;
|
map<perm_string,Module*>::iterator mod;
|
||||||
for (mod = pform_modules.begin()
|
for (mod = pform_modules.begin()
|
||||||
; mod != pform_modules.end() ; mod++) {
|
; mod != pform_modules.end() ; mod++) {
|
||||||
const Module*mp = (*mod).second;
|
Module*mp = (*mod).second;
|
||||||
|
if (mp->time_from_timescale ||
|
||||||
|
mp->timescale_warn_done) continue;
|
||||||
|
mp->timescale_warn_done = true;
|
||||||
|
|
||||||
cerr << file << ":" << lineno << ": : "
|
cerr << file << ":" << lineno << ": : "
|
||||||
<< " -- module " << (*mod).first
|
<< " -- module " << (*mod).first
|
||||||
|
|
@ -342,6 +399,9 @@ void pform_startmodule(const char*name, const char*file, unsigned lineno,
|
||||||
pform_cur_module = new Module(lex_name);
|
pform_cur_module = new Module(lex_name);
|
||||||
pform_cur_module->time_unit = pform_time_unit;
|
pform_cur_module->time_unit = pform_time_unit;
|
||||||
pform_cur_module->time_precision = pform_time_prec;
|
pform_cur_module->time_precision = pform_time_prec;
|
||||||
|
/* If we have a timescale file then the time information is from
|
||||||
|
* a timescale directive. */
|
||||||
|
pform_cur_module->time_from_timescale = pform_timescale_file != 0;
|
||||||
pform_cur_module->default_nettype = pform_default_nettype;
|
pform_cur_module->default_nettype = pform_default_nettype;
|
||||||
|
|
||||||
FILE_NAME(pform_cur_module, file, lineno);
|
FILE_NAME(pform_cur_module, file, lineno);
|
||||||
|
|
@ -407,11 +467,14 @@ void pform_module_set_ports(vector<Module::port_t*>*ports)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pform_endmodule(const char*name)
|
void pform_endmodule(const char*name, bool in_celldefine,
|
||||||
|
Module::UCDriveType uc_drive)
|
||||||
{
|
{
|
||||||
assert(pform_cur_module);
|
assert(pform_cur_module);
|
||||||
perm_string mod_name = pform_cur_module->mod_name();
|
perm_string mod_name = pform_cur_module->mod_name();
|
||||||
assert(strcmp(name, mod_name) == 0);
|
assert(strcmp(name, mod_name) == 0);
|
||||||
|
pform_cur_module->is_cell = in_celldefine;
|
||||||
|
pform_cur_module->uc_drive = uc_drive;
|
||||||
|
|
||||||
map<perm_string,Module*>::const_iterator test =
|
map<perm_string,Module*>::const_iterator test =
|
||||||
pform_modules.find(mod_name);
|
pform_modules.find(mod_name);
|
||||||
|
|
@ -434,13 +497,31 @@ void pform_endmodule(const char*name)
|
||||||
pform_cur_module = 0;
|
pform_cur_module = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void pform_add_genvar(const struct vlltype&li, const perm_string&name,
|
||||||
|
map<perm_string,LineInfo*>&genvars)
|
||||||
|
{
|
||||||
|
LineInfo*lni = new LineInfo();
|
||||||
|
FILE_NAME(lni, li);
|
||||||
|
if (genvars.find(name) != genvars.end()) {
|
||||||
|
cerr << lni->get_fileline() << ": error: genvar '"
|
||||||
|
<< name << "' has already been declared." << endl;
|
||||||
|
cerr << genvars[name]->get_fileline()
|
||||||
|
<< ": the previous declaration is here." << endl;
|
||||||
|
error_count += 1;
|
||||||
|
delete lni;
|
||||||
|
} else {
|
||||||
|
genvars[name] = lni;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void pform_genvars(const struct vlltype&li, list<perm_string>*names)
|
void pform_genvars(const struct vlltype&li, list<perm_string>*names)
|
||||||
{
|
{
|
||||||
list<perm_string>::const_iterator cur;
|
list<perm_string>::const_iterator cur;
|
||||||
for (cur = names->begin(); cur != names->end() ; *cur++) {
|
for (cur = names->begin(); cur != names->end() ; *cur++) {
|
||||||
LineInfo*lni = new LineInfo();
|
if (pform_cur_generate)
|
||||||
FILE_NAME(lni, li);
|
pform_add_genvar(li, *cur, pform_cur_generate->genvars);
|
||||||
pform_cur_module->genvars[*cur] = lni;
|
else
|
||||||
|
pform_add_genvar(li, *cur, pform_cur_module->genvars);
|
||||||
}
|
}
|
||||||
|
|
||||||
delete names;
|
delete names;
|
||||||
|
|
@ -455,7 +536,6 @@ void pform_start_generate_for(const struct vlltype&li,
|
||||||
|
|
||||||
FILE_NAME(gen, li);
|
FILE_NAME(gen, li);
|
||||||
|
|
||||||
// For now, assume that generates do not nest.
|
|
||||||
gen->parent = pform_cur_generate;
|
gen->parent = pform_cur_generate;
|
||||||
pform_cur_generate = gen;
|
pform_cur_generate = gen;
|
||||||
|
|
||||||
|
|
@ -476,7 +556,6 @@ void pform_start_generate_if(const struct vlltype&li, PExpr*test)
|
||||||
|
|
||||||
FILE_NAME(gen, li);
|
FILE_NAME(gen, li);
|
||||||
|
|
||||||
// For now, assume that generates do not nest.
|
|
||||||
gen->parent = pform_cur_generate;
|
gen->parent = pform_cur_generate;
|
||||||
pform_cur_generate = gen;
|
pform_cur_generate = gen;
|
||||||
|
|
||||||
|
|
@ -499,7 +578,6 @@ void pform_start_generate_else(const struct vlltype&li)
|
||||||
|
|
||||||
FILE_NAME(gen, li);
|
FILE_NAME(gen, li);
|
||||||
|
|
||||||
// For now, assume that generates do not nest.
|
|
||||||
gen->parent = pform_cur_generate;
|
gen->parent = pform_cur_generate;
|
||||||
pform_cur_generate = gen;
|
pform_cur_generate = gen;
|
||||||
|
|
||||||
|
|
@ -1028,13 +1106,13 @@ static void pform_set_net_range(perm_string name,
|
||||||
if (range == 0) {
|
if (range == 0) {
|
||||||
/* This is the special case that we really mean a
|
/* This is the special case that we really mean a
|
||||||
scalar. Set a fake range. */
|
scalar. Set a fake range. */
|
||||||
cur->set_range(0, 0, rt);
|
cur->set_range(0, 0, rt, true);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
assert(range->count() == 2);
|
assert(range->count() == 2);
|
||||||
assert((*range)[0]);
|
assert((*range)[0]);
|
||||||
assert((*range)[1]);
|
assert((*range)[1]);
|
||||||
cur->set_range((*range)[0], (*range)[1], rt);
|
cur->set_range((*range)[0], (*range)[1], rt, false);
|
||||||
}
|
}
|
||||||
cur->set_signed(signed_flag);
|
cur->set_signed(signed_flag);
|
||||||
|
|
||||||
|
|
@ -1068,9 +1146,21 @@ void pform_set_net_range(list<perm_string>*names,
|
||||||
*/
|
*/
|
||||||
static void pform_make_event(perm_string name, const char*fn, unsigned ln)
|
static void pform_make_event(perm_string name, const char*fn, unsigned ln)
|
||||||
{
|
{
|
||||||
|
LexicalScope*scope = pform_get_cur_scope();
|
||||||
|
|
||||||
|
// Check if the named event is already in the dictionary.
|
||||||
|
if (scope->events.find(name) != scope->events.end()) {
|
||||||
|
LineInfo tloc;
|
||||||
|
FILE_NAME(&tloc, fn, ln);
|
||||||
|
cerr << tloc.get_fileline() << ": error: duplicate definition "
|
||||||
|
"for named event '" << name << "' in '"
|
||||||
|
<< pform_cur_module->mod_name() << "'." << endl;
|
||||||
|
error_count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
PEvent*event = new PEvent(name);
|
PEvent*event = new PEvent(name);
|
||||||
FILE_NAME(event, fn, ln);
|
FILE_NAME(event, fn, ln);
|
||||||
pform_get_cur_scope()->events[name] = event;
|
scope->events[name] = event;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pform_make_events(list<perm_string>*names, const char*fn, unsigned ln)
|
void pform_make_events(list<perm_string>*names, const char*fn, unsigned ln)
|
||||||
|
|
@ -1396,14 +1486,16 @@ void pform_module_define_port(const struct vlltype&li,
|
||||||
|
|
||||||
if (range == 0) {
|
if (range == 0) {
|
||||||
cur->set_range(0, 0, (type == NetNet::IMPLICIT) ? SR_PORT :
|
cur->set_range(0, 0, (type == NetNet::IMPLICIT) ? SR_PORT :
|
||||||
SR_BOTH);
|
SR_BOTH,
|
||||||
|
true);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
assert(range->count() == 2);
|
assert(range->count() == 2);
|
||||||
assert((*range)[0]);
|
assert((*range)[0]);
|
||||||
assert((*range)[1]);
|
assert((*range)[1]);
|
||||||
cur->set_range((*range)[0], (*range)[1],
|
cur->set_range((*range)[0], (*range)[1],
|
||||||
(type == NetNet::IMPLICIT) ? SR_PORT : SR_BOTH);
|
(type == NetNet::IMPLICIT) ? SR_PORT : SR_BOTH,
|
||||||
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attr) {
|
if (attr) {
|
||||||
|
|
@ -1483,7 +1575,7 @@ void pform_makewire(const vlltype&li, perm_string name,
|
||||||
<< " to " << dt << "." << endl;
|
<< " to " << dt << "." << endl;
|
||||||
}
|
}
|
||||||
ivl_assert(*cur, flag);
|
ivl_assert(*cur, flag);
|
||||||
cur->set_range(0, 0, SR_NET);
|
cur->set_range(0, 0, SR_NET, true);
|
||||||
cur->set_signed(true);
|
cur->set_signed(true);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
@ -1673,7 +1765,7 @@ svector<PWire*>*pform_make_task_ports(NetNet::PortType pt,
|
||||||
|
|
||||||
/* If there is a range involved, it needs to be set. */
|
/* If there is a range involved, it needs to be set. */
|
||||||
if (range)
|
if (range)
|
||||||
curw->set_range((*range)[0], (*range)[1], SR_PORT);
|
curw->set_range((*range)[0], (*range)[1], SR_PORT, false);
|
||||||
|
|
||||||
svector<PWire*>*tmp = new svector<PWire*>(*res, curw);
|
svector<PWire*>*tmp = new svector<PWire*>(*res, curw);
|
||||||
|
|
||||||
|
|
@ -1763,13 +1855,32 @@ void pform_set_parameter(const struct vlltype&loc,
|
||||||
bool signed_flag, svector<PExpr*>*range, PExpr*expr,
|
bool signed_flag, svector<PExpr*>*range, PExpr*expr,
|
||||||
LexicalScope::range_t*value_range)
|
LexicalScope::range_t*value_range)
|
||||||
{
|
{
|
||||||
if (pform_get_cur_scope() == pform_cur_generate) {
|
LexicalScope*scope = pform_get_cur_scope();
|
||||||
|
if (scope == pform_cur_generate) {
|
||||||
VLerror("parameter declarations are not permitted in generate blocks");
|
VLerror("parameter declarations are not permitted in generate blocks");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if the parameter name is already in the dictionary.
|
||||||
|
if (scope->parameters.find(name) != scope->parameters.end()) {
|
||||||
|
LineInfo tloc;
|
||||||
|
FILE_NAME(&tloc, loc);
|
||||||
|
cerr << tloc.get_fileline() << ": error: duplicate definition "
|
||||||
|
"for parameter '" << name << "' in '"
|
||||||
|
<< pform_cur_module->mod_name() << "'." << endl;
|
||||||
|
error_count += 1;
|
||||||
|
}
|
||||||
|
if (scope->localparams.find(name) != scope->localparams.end()) {
|
||||||
|
LineInfo tloc;
|
||||||
|
FILE_NAME(&tloc, loc);
|
||||||
|
cerr << tloc.get_fileline() << ": error: localparam and "
|
||||||
|
"parameter in '" << pform_cur_module->mod_name()
|
||||||
|
<< "' have the same name '" << name << "'." << endl;
|
||||||
|
error_count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
assert(expr);
|
assert(expr);
|
||||||
Module::param_expr_t&parm = pform_get_cur_scope()->parameters[name];
|
Module::param_expr_t&parm = scope->parameters[name];
|
||||||
FILE_NAME(&parm, loc);
|
FILE_NAME(&parm, loc);
|
||||||
|
|
||||||
parm.expr = expr;
|
parm.expr = expr;
|
||||||
|
|
@ -1788,7 +1899,7 @@ void pform_set_parameter(const struct vlltype&loc,
|
||||||
parm.signed_flag = signed_flag;
|
parm.signed_flag = signed_flag;
|
||||||
parm.range = value_range;
|
parm.range = value_range;
|
||||||
|
|
||||||
if (pform_get_cur_scope() == pform_cur_module)
|
if (scope == pform_cur_module)
|
||||||
pform_cur_module->param_names.push_back(name);
|
pform_cur_module->param_names.push_back(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1796,6 +1907,26 @@ void pform_set_localparam(const struct vlltype&loc,
|
||||||
perm_string name, ivl_variable_type_t type,
|
perm_string name, ivl_variable_type_t type,
|
||||||
bool signed_flag, svector<PExpr*>*range, PExpr*expr)
|
bool signed_flag, svector<PExpr*>*range, PExpr*expr)
|
||||||
{
|
{
|
||||||
|
LexicalScope*scope = pform_get_cur_scope();
|
||||||
|
|
||||||
|
// Check if the localparam name is already in the dictionary.
|
||||||
|
if (scope->localparams.find(name) != scope->localparams.end()) {
|
||||||
|
LineInfo tloc;
|
||||||
|
FILE_NAME(&tloc, loc);
|
||||||
|
cerr << tloc.get_fileline() << ": error: duplicate definition "
|
||||||
|
"for localparam '" << name << "' in '"
|
||||||
|
<< pform_cur_module->mod_name() << "'." << endl;
|
||||||
|
error_count += 1;
|
||||||
|
}
|
||||||
|
if (scope->parameters.find(name) != scope->parameters.end()) {
|
||||||
|
LineInfo tloc;
|
||||||
|
FILE_NAME(&tloc, loc);
|
||||||
|
cerr << tloc.get_fileline() << ": error: parameter and "
|
||||||
|
"localparam in '" << pform_cur_module->mod_name()
|
||||||
|
<< "' have the same name '" << name << "'." << endl;
|
||||||
|
error_count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
assert(expr);
|
assert(expr);
|
||||||
Module::param_expr_t&parm = pform_get_cur_scope()->localparams[name];
|
Module::param_expr_t&parm = pform_get_cur_scope()->localparams[name];
|
||||||
FILE_NAME(&parm, loc);
|
FILE_NAME(&parm, loc);
|
||||||
|
|
@ -1819,6 +1950,15 @@ void pform_set_localparam(const struct vlltype&loc,
|
||||||
|
|
||||||
void pform_set_specparam(perm_string name, PExpr*expr)
|
void pform_set_specparam(perm_string name, PExpr*expr)
|
||||||
{
|
{
|
||||||
|
// Check if the specparam name is already in the dictionary.
|
||||||
|
if (pform_cur_module->specparams.find(name) !=
|
||||||
|
pform_cur_module->specparams.end()) {
|
||||||
|
cerr << expr->get_fileline() << ": error: duplicate definition "
|
||||||
|
"for specparam '" << name << "' in '"
|
||||||
|
<< pform_cur_module->mod_name() << "'." << endl;
|
||||||
|
error_count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
assert(expr);
|
assert(expr);
|
||||||
pform_cur_module->specparams[name] = expr;
|
pform_cur_module->specparams[name] = expr;
|
||||||
}
|
}
|
||||||
|
|
@ -1933,7 +2073,7 @@ static void pform_set_reg_integer(perm_string name)
|
||||||
|
|
||||||
cur->set_range(new PENumber(new verinum(integer_width-1, integer_width)),
|
cur->set_range(new PENumber(new verinum(integer_width-1, integer_width)),
|
||||||
new PENumber(new verinum((uint64_t)0, integer_width)),
|
new PENumber(new verinum((uint64_t)0, integer_width)),
|
||||||
SR_NET);
|
SR_NET, false);
|
||||||
cur->set_signed(true);
|
cur->set_signed(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1964,7 +2104,7 @@ static void pform_set_reg_time(perm_string name)
|
||||||
|
|
||||||
cur->set_range(new PENumber(new verinum(TIME_WIDTH-1, integer_width)),
|
cur->set_range(new PENumber(new verinum(TIME_WIDTH-1, integer_width)),
|
||||||
new PENumber(new verinum((uint64_t)0, integer_width)),
|
new PENumber(new verinum((uint64_t)0, integer_width)),
|
||||||
SR_NET);
|
SR_NET, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pform_set_reg_time(list<perm_string>*names)
|
void pform_set_reg_time(list<perm_string>*names)
|
||||||
|
|
@ -2045,6 +2185,7 @@ int pform_parse(const char*path, FILE*file)
|
||||||
error_count += 1;
|
error_count += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
destroy_lexor();
|
||||||
return error_count;
|
return error_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
13
pform.h
13
pform.h
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef __pform_H
|
#ifndef __pform_H
|
||||||
#define __pform_H
|
#define __pform_H
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1998-2008 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 1998-2009 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -159,7 +159,8 @@ extern void pform_module_define_port(const struct vlltype&li,
|
||||||
extern Module::port_t* pform_module_port_reference(perm_string name,
|
extern Module::port_t* pform_module_port_reference(perm_string name,
|
||||||
const char*file,
|
const char*file,
|
||||||
unsigned lineno);
|
unsigned lineno);
|
||||||
extern void pform_endmodule(const char*);
|
extern void pform_endmodule(const char*, bool in_celldefine,
|
||||||
|
Module::UCDriveType uc_drive);
|
||||||
|
|
||||||
extern void pform_make_udp(perm_string name, list<perm_string>*parms,
|
extern void pform_make_udp(perm_string name, list<perm_string>*parms,
|
||||||
svector<PWire*>*decl, list<string>*table,
|
svector<PWire*>*decl, list<string>*table,
|
||||||
|
|
@ -180,8 +181,10 @@ extern void pform_make_udp(perm_string name,
|
||||||
*/
|
*/
|
||||||
extern void pform_pop_scope();
|
extern void pform_pop_scope();
|
||||||
|
|
||||||
extern PTask*pform_push_task_scope(char*name, bool is_auto);
|
extern PTask*pform_push_task_scope(const struct vlltype&loc, char*name,
|
||||||
extern PFunction*pform_push_function_scope(char*name, bool is_auto);
|
bool is_auto);
|
||||||
|
extern PFunction*pform_push_function_scope(const struct vlltype&loc, char*name,
|
||||||
|
bool is_auto);
|
||||||
extern PBlock*pform_push_block_scope(char*name, PBlock::BL_TYPE tt);
|
extern PBlock*pform_push_block_scope(char*name, PBlock::BL_TYPE tt);
|
||||||
|
|
||||||
extern void pform_put_behavior_in_scope(AProcess*proc);
|
extern void pform_put_behavior_in_scope(AProcess*proc);
|
||||||
|
|
@ -191,7 +194,7 @@ extern verinum* pform_verinum_with_size(verinum*s, verinum*val,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function takes the list of names as new genvars to declare in
|
* This function takes the list of names as new genvars to declare in
|
||||||
* the current module scope.
|
* the current module or generate scope.
|
||||||
*/
|
*/
|
||||||
extern void pform_genvars(const struct vlltype&li, list<perm_string>*names);
|
extern void pform_genvars(const struct vlltype&li, list<perm_string>*names);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1998-2008 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 1998-2009 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -410,6 +410,8 @@ void PDelays::dump_delays(ostream&out) const
|
||||||
if (delay_[0] && delay_[1] && delay_[2])
|
if (delay_[0] && delay_[1] && delay_[2])
|
||||||
out << "#(" << *delay_[0] << "," << *delay_[1] << "," <<
|
out << "#(" << *delay_[0] << "," << *delay_[1] << "," <<
|
||||||
*delay_[2] << ")";
|
*delay_[2] << ")";
|
||||||
|
else if (delay_[0] && delay_[1])
|
||||||
|
out << "#(" << *delay_[0] << "," << *delay_[1] << ")";
|
||||||
else if (delay_[0])
|
else if (delay_[0])
|
||||||
out << "#" << *delay_[0];
|
out << "#" << *delay_[0];
|
||||||
else
|
else
|
||||||
|
|
@ -1032,6 +1034,12 @@ void PGenerate::dump(ostream&out, unsigned indent) const
|
||||||
(*idx)->dump(out, indent+2);
|
(*idx)->dump(out, indent+2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef map<perm_string,LineInfo*>::const_iterator genvar_iter_t;
|
||||||
|
for (genvar_iter_t cur = genvars.begin()
|
||||||
|
; cur != genvars.end() ; cur++) {
|
||||||
|
out << setw(indent+2) << "" << "genvar " << ((*cur).first) << ";" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
for (list<PGenerate*>::const_iterator idx = generate_schemes.begin()
|
for (list<PGenerate*>::const_iterator idx = generate_schemes.begin()
|
||||||
; idx != generate_schemes.end() ; idx++) {
|
; idx != generate_schemes.end() ; idx++) {
|
||||||
(*idx)->dump(out, indent+2);
|
(*idx)->dump(out, indent+2);
|
||||||
|
|
@ -1147,7 +1155,9 @@ void Module::dump(ostream&out) const
|
||||||
out << " *) ";
|
out << " *) ";
|
||||||
}
|
}
|
||||||
|
|
||||||
out << "module " << mod_name() << ";" << endl;
|
out << "module " << mod_name() << ";";
|
||||||
|
if (is_cell) out << " // Is in `celldefine.";
|
||||||
|
out << endl;
|
||||||
|
|
||||||
for (unsigned idx = 0 ; idx < ports.size() ; idx += 1) {
|
for (unsigned idx = 0 ; idx < ports.size() ; idx += 1) {
|
||||||
port_t*cur = ports[idx];
|
port_t*cur = ports[idx];
|
||||||
|
|
|
||||||
|
|
@ -10,4 +10,6 @@
|
||||||
|
|
||||||
echo "Building version_tag.h with git describe"
|
echo "Building version_tag.h with git describe"
|
||||||
tmp=`git describe | sed -e 's;\(.*\);#define VERSION_TAG "\1";'`
|
tmp=`git describe | sed -e 's;\(.*\);#define VERSION_TAG "\1";'`
|
||||||
echo "$tmp" > version_tag.h
|
echo "#ifndef VERSION_TAG" > version_tag.h
|
||||||
|
echo "$tmp" >> version_tag.h
|
||||||
|
echo "#endif" >> version_tag.h
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,65 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# This script makes a release from a git repository. The input is
|
||||||
|
# the number for a snapshot and the path to a temporary directory.
|
||||||
|
# for example:
|
||||||
|
#
|
||||||
|
# sh scripts/MAKE_RELEASE.sh 0.9.1 ~/tmp
|
||||||
|
#
|
||||||
|
# The above assumes that there is a tag "v0_9_1" at the point
|
||||||
|
# to be released. (The tag has the "v", but the argument to this
|
||||||
|
# script does not have the "v"). This script extracts based on the
|
||||||
|
# tag, uses the temporary directory to stage intermediate results,
|
||||||
|
# and finally creates a file called verilog-0.9.1.tar.gz that
|
||||||
|
# contains the release ready to go.
|
||||||
|
#
|
||||||
|
# The complete steps to make a release x.y.z generally are:
|
||||||
|
#
|
||||||
|
# git tag -a v0_9_1
|
||||||
|
# (Make the tag in the local git repository.)
|
||||||
|
#
|
||||||
|
# sh scripts/MAKE_RELEASE.sh 0.9.1 ~/tmp
|
||||||
|
# (Make the snapshot bundle verilog-0.9.1.tar.gz)
|
||||||
|
#
|
||||||
|
# git push --tags
|
||||||
|
# (Publish the tag to the repository.)
|
||||||
|
#
|
||||||
|
id=$1
|
||||||
|
destdir=$2
|
||||||
|
|
||||||
|
# The git tag to use.
|
||||||
|
tag="v"`echo $id | tr '.' '_'`
|
||||||
|
|
||||||
|
# The prefix is the directory that contains the extracted files
|
||||||
|
# of the bundle. This is also the name of the bundle file itself.
|
||||||
|
prefix="verilog-$id"
|
||||||
|
|
||||||
|
if [ ! -d $destdir ]; then
|
||||||
|
echo "ERROR: Directory $destdir does not exist."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -e $destdir/$prefix ]; then
|
||||||
|
echo "ERROR: $destdir/$prefix already exists."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Exporting $tag to $destdir/$prefix..."
|
||||||
|
git archive --prefix="$prefix/" $tag | ( cd "$destdir" && tar xf - )
|
||||||
|
|
||||||
|
versionh="$destdir/$prefix/version_tag.h"
|
||||||
|
echo "Create $versionh ..."
|
||||||
|
echo "#ifndef VERSION_TAG" > $versionh
|
||||||
|
echo "#define VERSION_TAG \"$tag\"" >> $versionh
|
||||||
|
echo "#endif" >> $versionh
|
||||||
|
|
||||||
|
echo "Running autoconf.sh..."
|
||||||
|
( cd $destdir/$prefix && sh autoconf.sh )
|
||||||
|
|
||||||
|
echo "Making bundle $prefix.tar.gz..."
|
||||||
|
tar czf $prefix.tar.gz --exclude=autom4te.cache -C "$destdir" $prefix
|
||||||
|
|
||||||
|
echo "Removing temporary $destdir/$prefix..."
|
||||||
|
rm -rf "$destdir/$prefix"
|
||||||
|
|
||||||
|
echo done
|
||||||
|
|
@ -47,9 +47,11 @@ fi
|
||||||
echo "Exporting $tag to $destdir/$prefix..."
|
echo "Exporting $tag to $destdir/$prefix..."
|
||||||
git archive --prefix="$prefix/" $tag | ( cd "$destdir" && tar xf - )
|
git archive --prefix="$prefix/" $tag | ( cd "$destdir" && tar xf - )
|
||||||
|
|
||||||
versionh="$destdir/$prefix/version.h"
|
versionh="$destdir/$prefix/version_tag.h"
|
||||||
echo "Create $versionh ..."
|
echo "Create $versionh ..."
|
||||||
echo "#define VERSION_TAG \"$tag\"" > $versionh
|
echo "#ifndef VERSION_TAG" > $versionh
|
||||||
|
echo "#define VERSION_TAG \"$tag\"" >> $versionh
|
||||||
|
echo "#endif" >> $versionh
|
||||||
|
|
||||||
echo "Running autoconf.sh..."
|
echo "Running autoconf.sh..."
|
||||||
( cd $destdir/$prefix && sh autoconf.sh )
|
( cd $destdir/$prefix && sh autoconf.sh )
|
||||||
|
|
|
||||||
38
set_width.cc
38
set_width.cc
|
|
@ -106,6 +106,18 @@ bool NetEBAdd::set_width(unsigned w, bool)
|
||||||
return wid == w;
|
return wid == w;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NetEBAdd::cast_signed(bool sign_flag)
|
||||||
|
{
|
||||||
|
if (has_sign() == sign_flag)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (sign_flag == false) {
|
||||||
|
left_->cast_signed(sign_flag);
|
||||||
|
right_->cast_signed(sign_flag);
|
||||||
|
}
|
||||||
|
cast_signed_base_(sign_flag);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The bitwise logical operators have operands the same size as the
|
* The bitwise logical operators have operands the same size as the
|
||||||
* result. Anything else is a mess. I first try to get the operands to
|
* result. Anything else is a mess. I first try to get the operands to
|
||||||
|
|
@ -168,6 +180,19 @@ bool NetEBDiv::set_width(unsigned w, bool)
|
||||||
return w == expr_width();
|
return w == expr_width();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NetEBDiv::cast_signed(bool sign_flag)
|
||||||
|
{
|
||||||
|
if (has_sign() == sign_flag)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (sign_flag == false) {
|
||||||
|
left_->cast_signed(sign_flag);
|
||||||
|
right_->cast_signed(sign_flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
cast_signed_base_(sign_flag);
|
||||||
|
}
|
||||||
|
|
||||||
bool NetEBLogic::set_width(unsigned w, bool)
|
bool NetEBLogic::set_width(unsigned w, bool)
|
||||||
{
|
{
|
||||||
bool flag;
|
bool flag;
|
||||||
|
|
@ -192,6 +217,19 @@ bool NetEBMult::set_width(unsigned w, bool)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NetEBMult::cast_signed(bool sign_flag)
|
||||||
|
{
|
||||||
|
if (has_sign() == sign_flag)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (sign_flag == false) {
|
||||||
|
left_->cast_signed(sign_flag);
|
||||||
|
right_->cast_signed(sign_flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
cast_signed_base_(sign_flag);
|
||||||
|
}
|
||||||
|
|
||||||
bool NetEBPow::set_width(unsigned w, bool last_chance)
|
bool NetEBPow::set_width(unsigned w, bool last_chance)
|
||||||
{
|
{
|
||||||
return w == expr_width();
|
return w == expr_width();
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,3 @@
|
||||||
# $Id: README-solaris_pkg.txt,v 1.3 2007/02/26 19:49:49 steve Exp $
|
|
||||||
|
|
||||||
Notes about the solaris package.
|
Notes about the solaris package.
|
||||||
|
|
||||||
I. Installing a prebuilt solaris package
|
I. Installing a prebuilt solaris package
|
||||||
|
|
|
||||||
14
sys_funcs.cc
14
sys_funcs.cc
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2004-2008 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2004-2009 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -46,6 +46,16 @@ struct sfunc_return_type_cell : sfunc_return_type {
|
||||||
|
|
||||||
static struct sfunc_return_type_cell*sfunc_stack = 0;
|
static struct sfunc_return_type_cell*sfunc_stack = 0;
|
||||||
|
|
||||||
|
void cleanup_sys_func_table()
|
||||||
|
{
|
||||||
|
struct sfunc_return_type_cell *next, *cur = sfunc_stack;
|
||||||
|
while (cur) {
|
||||||
|
next = cur->next;
|
||||||
|
delete cur;
|
||||||
|
cur = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const struct sfunc_return_type* lookup_sys_func(const char*name)
|
const struct sfunc_return_type* lookup_sys_func(const char*name)
|
||||||
{
|
{
|
||||||
/* First, try to find then name in the function stack. */
|
/* First, try to find then name in the function stack. */
|
||||||
|
|
@ -186,7 +196,7 @@ int load_sys_func_table(const char*path)
|
||||||
fprintf(stderr, "%s:%s: Unknown type: %s\n",
|
fprintf(stderr, "%s:%s: Unknown type: %s\n",
|
||||||
path, name, stype);
|
path, name, stype);
|
||||||
}
|
}
|
||||||
|
fclose(fd);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
21
t-dll-api.cc
21
t-dll-api.cc
|
|
@ -1268,6 +1268,8 @@ extern "C" unsigned ivl_lpm_size(ivl_lpm_t net)
|
||||||
return net->u_.ufunc.ports - 1;
|
return net->u_.ufunc.ports - 1;
|
||||||
case IVL_LPM_REPEAT:
|
case IVL_LPM_REPEAT:
|
||||||
return net->u_.repeat.count;
|
return net->u_.repeat.count;
|
||||||
|
case IVL_LPM_CONCAT:
|
||||||
|
return net->u_.concat.inputs;
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -1655,6 +1657,12 @@ extern "C" unsigned ivl_scope_is_auto(ivl_scope_t net)
|
||||||
return net->is_auto;
|
return net->is_auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" unsigned ivl_scope_is_cell(ivl_scope_t net)
|
||||||
|
{
|
||||||
|
assert(net);
|
||||||
|
return net->is_cell;
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" unsigned ivl_scope_lineno(ivl_scope_t net)
|
extern "C" unsigned ivl_scope_lineno(ivl_scope_t net)
|
||||||
{
|
{
|
||||||
assert(net);
|
assert(net);
|
||||||
|
|
@ -1893,10 +1901,17 @@ extern "C" const char* ivl_signal_name(ivl_signal_t net)
|
||||||
extern "C" ivl_nexus_t ivl_signal_nex(ivl_signal_t net, unsigned word)
|
extern "C" ivl_nexus_t ivl_signal_nex(ivl_signal_t net, unsigned word)
|
||||||
{
|
{
|
||||||
assert(word < net->array_words);
|
assert(word < net->array_words);
|
||||||
if (net->array_words > 1)
|
if (net->array_words > 1) {
|
||||||
return net->pins[word];
|
if (net->pins) {
|
||||||
else
|
return net->pins[word];
|
||||||
|
} else {
|
||||||
|
// net->pins can be NULL for a virtualized reg array.
|
||||||
|
assert(net->type_ == IVL_SIT_REG);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
return net->pin;
|
return net->pin;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" int ivl_signal_msb(ivl_signal_t net)
|
extern "C" int ivl_signal_msb(ivl_signal_t net)
|
||||||
|
|
|
||||||
|
|
@ -199,7 +199,7 @@ void dll_target::expr_concat(const NetEConcat*net)
|
||||||
cur->type_ = IVL_EX_CONCAT;
|
cur->type_ = IVL_EX_CONCAT;
|
||||||
cur->value_ = IVL_VT_VECTOR;
|
cur->value_ = IVL_VT_VECTOR;
|
||||||
cur->width_ = net->expr_width();
|
cur->width_ = net->expr_width();
|
||||||
cur->signed_ = 0;
|
cur->signed_ = net->has_sign() ? 1 : 0;
|
||||||
|
|
||||||
cur->u_.concat_.rept = net->repeat();
|
cur->u_.concat_.rept = net->repeat();
|
||||||
cur->u_.concat_.parms = net->nparms();
|
cur->u_.concat_.parms = net->nparms();
|
||||||
|
|
@ -308,6 +308,7 @@ void dll_target::expr_event(const NetEEvent*net)
|
||||||
assert(expr_);
|
assert(expr_);
|
||||||
|
|
||||||
expr_->type_ = IVL_EX_EVENT;
|
expr_->type_ = IVL_EX_EVENT;
|
||||||
|
FILE_NAME(expr_, net);
|
||||||
expr_->value_= IVL_VT_VOID;
|
expr_->value_= IVL_VT_VOID;
|
||||||
|
|
||||||
/* Locate the event by name. Save the ivl_event_t in the
|
/* Locate the event by name. Save the ivl_event_t in the
|
||||||
|
|
@ -351,6 +352,7 @@ void dll_target::expr_select(const NetESelect*net)
|
||||||
|
|
||||||
expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
|
expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
|
||||||
assert(expr_);
|
assert(expr_);
|
||||||
|
FILE_NAME(expr_, net);
|
||||||
|
|
||||||
expr_->type_ = IVL_EX_SELECT;
|
expr_->type_ = IVL_EX_SELECT;
|
||||||
expr_->value_= IVL_VT_VECTOR;
|
expr_->value_= IVL_VT_VECTOR;
|
||||||
|
|
@ -450,10 +452,10 @@ void dll_target::expr_signal(const NetESignal*net)
|
||||||
|
|
||||||
/* Make account for the special case that this is a reference
|
/* Make account for the special case that this is a reference
|
||||||
to an array as a whole. We detect this case by noting that
|
to an array as a whole. We detect this case by noting that
|
||||||
this is an array (more than 1 word) and there is no word
|
this is an array (more than 0 array dimensions) and that
|
||||||
select expression. In that case, this is an IVL_EX_ARRAY
|
there is no word select expression. For this case, we have
|
||||||
expression instead of a SIGNAL expression. */
|
an IVL_EX_ARRAY expression instead of a SIGNAL expression. */
|
||||||
if (sig->array_words > 1 && word_expr == 0) {
|
if (sig->array_dimensions_ > 0 && word_expr == 0) {
|
||||||
expr_->type_ = IVL_EX_ARRAY;
|
expr_->type_ = IVL_EX_ARRAY;
|
||||||
expr_->width_ = 0; // Doesn't make much sense for arrays.
|
expr_->width_ = 0; // Doesn't make much sense for arrays.
|
||||||
}
|
}
|
||||||
|
|
|
||||||
19
t-dll.cc
19
t-dll.cc
|
|
@ -2147,6 +2147,7 @@ bool dll_target::part_select(const NetPartSelect*net)
|
||||||
obj->type = IVL_LPM_PART_PV;
|
obj->type = IVL_LPM_PART_PV;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
FILE_NAME(obj, net);
|
||||||
obj->name = net->name(); // NetPartSelect names are permallocated.
|
obj->name = net->name(); // NetPartSelect names are permallocated.
|
||||||
assert(net->scope());
|
assert(net->scope());
|
||||||
obj->scope = find_scope(des_, net->scope());
|
obj->scope = find_scope(des_, net->scope());
|
||||||
|
|
@ -2389,6 +2390,7 @@ void dll_target::scope(const NetScope*net)
|
||||||
scop->nattr = net->attr_cnt();
|
scop->nattr = net->attr_cnt();
|
||||||
scop->attr = fill_in_attributes(net);
|
scop->attr = fill_in_attributes(net);
|
||||||
scop->is_auto = net->is_auto();
|
scop->is_auto = net->is_auto();
|
||||||
|
scop->is_cell = net->is_cell();
|
||||||
|
|
||||||
switch (net->type()) {
|
switch (net->type()) {
|
||||||
case NetScope::MODULE:
|
case NetScope::MODULE:
|
||||||
|
|
@ -2510,6 +2512,10 @@ void dll_target::signal(const NetNet*net)
|
||||||
assert(0);
|
assert(0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case NetNet::UWIRE:
|
||||||
|
cerr << net->get_fileline()
|
||||||
|
<< ": warning: uwire is not currently supported, converting "
|
||||||
|
"it to a wire!" << endl;
|
||||||
case NetNet::TRI:
|
case NetNet::TRI:
|
||||||
case NetNet::WIRE:
|
case NetNet::WIRE:
|
||||||
case NetNet::IMPLICIT:
|
case NetNet::IMPLICIT:
|
||||||
|
|
@ -2560,12 +2566,22 @@ void dll_target::signal(const NetNet*net)
|
||||||
obj->array_base = net->array_first();
|
obj->array_base = net->array_first();
|
||||||
obj->array_words = net->array_count();
|
obj->array_words = net->array_count();
|
||||||
obj->array_addr_swapped = net->array_addr_swapped() ? 1 : 0;
|
obj->array_addr_swapped = net->array_addr_swapped() ? 1 : 0;
|
||||||
|
|
||||||
|
assert(obj->array_words == net->pin_count());
|
||||||
|
if (debug_optimizer && obj->array_words > 1000) cerr << "debug: "
|
||||||
|
"t-dll creating nexus array " << obj->array_words << " long" << endl;
|
||||||
|
if (obj->array_words > 1 && net->pins_are_virtual()) {
|
||||||
|
obj->pins = NULL;
|
||||||
|
if (debug_optimizer && obj->array_words > 1000) cerr << "debug: "
|
||||||
|
"t-dll used NULL for big nexus array" << endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (obj->array_words > 1)
|
if (obj->array_words > 1)
|
||||||
obj->pins = new ivl_nexus_t[obj->array_words];
|
obj->pins = new ivl_nexus_t[obj->array_words];
|
||||||
|
|
||||||
for (unsigned idx = 0 ; idx < obj->array_words ; idx += 1) {
|
for (unsigned idx = 0 ; idx < obj->array_words ; idx += 1) {
|
||||||
|
|
||||||
const Nexus*nex = net->pin(idx).nexus();
|
const Nexus*nex = net->pins_are_virtual() ? 0 : net->pin(idx).nexus();
|
||||||
if (nex == 0) {
|
if (nex == 0) {
|
||||||
// Special case: This pin is connected to
|
// Special case: This pin is connected to
|
||||||
// nothing. This can happen, for example, if the
|
// nothing. This can happen, for example, if the
|
||||||
|
|
@ -2597,6 +2613,7 @@ void dll_target::signal(const NetNet*net)
|
||||||
obj->pin = tmp;
|
obj->pin = tmp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (debug_optimizer && obj->array_words > 1000) cerr << "debug: t-dll done with big nexus array" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool dll_target::signal_paths(const NetNet*net)
|
bool dll_target::signal_paths(const NetNet*net)
|
||||||
|
|
|
||||||
2
t-dll.h
2
t-dll.h
|
|
@ -606,6 +606,8 @@ struct ivl_scope_s {
|
||||||
ivl_statement_t def;
|
ivl_statement_t def;
|
||||||
unsigned is_auto;
|
unsigned is_auto;
|
||||||
|
|
||||||
|
unsigned is_cell;
|
||||||
|
|
||||||
unsigned ports;
|
unsigned ports;
|
||||||
ivl_signal_t*port;
|
ivl_signal_t*port;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@
|
||||||
FPGA LOADABLE CODE GENERATOR FOR Icarus Verilog
|
FPGA LOADABLE CODE GENERATOR FOR Icarus Verilog
|
||||||
|
|
||||||
Copyright 2001 Stephen Williams
|
Copyright 2001 Stephen Williams
|
||||||
$Id: fpga.txt,v 1.12 2005/09/19 21:45:36 steve Exp $
|
|
||||||
|
|
||||||
The FPGA code generator supports a variety of FPGA devices, writing
|
The FPGA code generator supports a variety of FPGA devices, writing
|
||||||
XNF or EDIF depending on the target. You can select the architecture
|
XNF or EDIF depending on the target. You can select the architecture
|
||||||
|
|
@ -186,42 +185,3 @@ Compile a single-file design with command line tools like so:
|
||||||
% map -o map.ncd foo.ngd
|
% map -o map.ncd foo.ngd
|
||||||
% par -w map.ncd foo.ncd
|
% par -w map.ncd foo.ncd
|
||||||
|
|
||||||
---
|
|
||||||
$Log: fpga.txt,v $
|
|
||||||
Revision 1.12 2005/09/19 21:45:36 steve
|
|
||||||
Spelling patches from Larry.
|
|
||||||
|
|
||||||
Revision 1.11 2003/08/07 05:17:34 steve
|
|
||||||
Add arch=lpm to the documentation.
|
|
||||||
|
|
||||||
Revision 1.10 2003/07/04 03:57:19 steve
|
|
||||||
Allow attributes on Verilog 2001 port declarations.
|
|
||||||
|
|
||||||
Revision 1.9 2003/07/04 01:08:03 steve
|
|
||||||
PAD attribute can be used to assign pins.
|
|
||||||
|
|
||||||
Revision 1.8 2003/07/02 00:26:49 steve
|
|
||||||
Fix spelling of part= flag.
|
|
||||||
|
|
||||||
Revision 1.7 2003/03/24 02:28:38 steve
|
|
||||||
Document the virtex2 architecture.
|
|
||||||
|
|
||||||
Revision 1.6 2003/03/24 00:47:54 steve
|
|
||||||
Add new virtex2 architecture family, and
|
|
||||||
also the new edif.h EDIF management functions.
|
|
||||||
|
|
||||||
Revision 1.5 2002/04/30 04:26:42 steve
|
|
||||||
Spelling errors.
|
|
||||||
|
|
||||||
Revision 1.4 2001/09/16 22:26:47 steve
|
|
||||||
Support the cellref attribute.
|
|
||||||
|
|
||||||
Revision 1.3 2001/09/16 01:48:16 steve
|
|
||||||
Suppor the PAD attribute on signals.
|
|
||||||
|
|
||||||
Revision 1.2 2001/09/06 04:28:40 steve
|
|
||||||
Separate the virtex and generic-edif code generators.
|
|
||||||
|
|
||||||
Revision 1.1 2001/09/02 23:58:49 steve
|
|
||||||
Add documentation for the code generator.
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -430,7 +430,7 @@ static void show_lpm_cmp_ne(ivl_lpm_t net)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* IVL_LPM_CONCAT
|
/* IVL_LPM_CONCAT
|
||||||
* The concat device takes N inputs (N=ivl_lpm_selects) and generates
|
* The concat device takes N inputs (N=ivl_lpm_size) and generates
|
||||||
* a single output. The total output is known from the ivl_lpm_width
|
* a single output. The total output is known from the ivl_lpm_width
|
||||||
* function. The widths of all the inputs are inferred from the widths
|
* function. The widths of all the inputs are inferred from the widths
|
||||||
* of the signals connected to the nexus of the inputs. The compiler
|
* of the signals connected to the nexus of the inputs. The compiler
|
||||||
|
|
@ -444,10 +444,10 @@ static void show_lpm_concat(ivl_lpm_t net)
|
||||||
unsigned width = ivl_lpm_width(net);
|
unsigned width = ivl_lpm_width(net);
|
||||||
|
|
||||||
fprintf(out, " LPM_CONCAT %s: <width=%u, inputs=%u>\n",
|
fprintf(out, " LPM_CONCAT %s: <width=%u, inputs=%u>\n",
|
||||||
ivl_lpm_basename(net), width, ivl_lpm_selects(net));
|
ivl_lpm_basename(net), width, ivl_lpm_size(net));
|
||||||
fprintf(out, " O: %p\n", ivl_lpm_q(net,0));
|
fprintf(out, " O: %p\n", ivl_lpm_q(net,0));
|
||||||
|
|
||||||
for (idx = 0 ; idx < ivl_lpm_selects(net) ; idx += 1) {
|
for (idx = 0 ; idx < ivl_lpm_size(net) ; idx += 1) {
|
||||||
ivl_nexus_t nex = ivl_lpm_data(net, idx);
|
ivl_nexus_t nex = ivl_lpm_data(net, idx);
|
||||||
unsigned signal_width = width_of_nexus(nex);
|
unsigned signal_width = width_of_nexus(nex);
|
||||||
|
|
||||||
|
|
@ -1272,15 +1272,21 @@ static void show_signal(ivl_signal_t net)
|
||||||
|
|
||||||
ivl_nexus_t nex = ivl_signal_nex(net, idx);
|
ivl_nexus_t nex = ivl_signal_nex(net, idx);
|
||||||
|
|
||||||
fprintf(out, " %s %s %s%s[%d:%d] %s[word=%u, adr=%d] <width=%u%s> <discipline=%s> nexus=%p\n",
|
fprintf(out, " %s %s %s%s[%d:%d] %s[word=%u, adr=%d] "
|
||||||
|
"<width=%u%s> <discipline=%s> ",
|
||||||
type, sign, port, data_type,
|
type, sign, port, data_type,
|
||||||
ivl_signal_msb(net), ivl_signal_lsb(net),
|
ivl_signal_msb(net), ivl_signal_lsb(net),
|
||||||
ivl_signal_basename(net),
|
ivl_signal_basename(net),
|
||||||
idx, ivl_signal_array_base(net)+idx,
|
idx, ivl_signal_array_base(net)+idx,
|
||||||
ivl_signal_width(net),
|
ivl_signal_width(net),
|
||||||
ivl_signal_local(net)? ", local":"",
|
ivl_signal_local(net)? ", local":"",
|
||||||
discipline_txt,
|
discipline_txt);
|
||||||
nex);
|
if (nex == NULL) {
|
||||||
|
fprintf(out, "nexus=<virtual>\n");
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
fprintf(out, "nexus=%p\n", nex);
|
||||||
|
}
|
||||||
|
|
||||||
show_nexus_details(net, nex);
|
show_nexus_details(net, nex);
|
||||||
}
|
}
|
||||||
|
|
@ -1527,7 +1533,8 @@ static int show_scope(ivl_scope_t net, void*x)
|
||||||
is_auto = ivl_scope_is_auto(net) ? "automatic " : "";
|
is_auto = ivl_scope_is_auto(net) ? "automatic " : "";
|
||||||
switch (ivl_scope_type(net)) {
|
switch (ivl_scope_type(net)) {
|
||||||
case IVL_SCT_MODULE:
|
case IVL_SCT_MODULE:
|
||||||
fprintf(out, " module %s", ivl_scope_tname(net));
|
fprintf(out, " module %s%s", ivl_scope_tname(net),
|
||||||
|
ivl_scope_is_cell(net) ? " (cell)" : "");
|
||||||
break;
|
break;
|
||||||
case IVL_SCT_FUNCTION:
|
case IVL_SCT_FUNCTION:
|
||||||
fprintf(out, " function %s%s", is_auto, ivl_scope_tname(net));
|
fprintf(out, " function %s%s", is_auto, ivl_scope_tname(net));
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* VHDL code generation for expressions.
|
* VHDL code generation for expressions.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2008 Nick Gasson (nick@nickg.me.uk)
|
* Copyright (C) 2008-2009 Nick Gasson (nick@nickg.me.uk)
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
|
@ -107,8 +107,10 @@ static vhdl_var_ref *translate_signal(ivl_expr_t e)
|
||||||
if (ivl_signal_array_count(sig) > 0 && (off = ivl_expr_oper1(e))) {
|
if (ivl_signal_array_count(sig) > 0 && (off = ivl_expr_oper1(e))) {
|
||||||
// Select from an array
|
// Select from an array
|
||||||
vhdl_expr *vhd_off = translate_expr(off);
|
vhdl_expr *vhd_off = translate_expr(off);
|
||||||
if (NULL == vhd_off)
|
if (NULL == vhd_off) {
|
||||||
|
delete ref;
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
vhdl_type integer(VHDL_TYPE_INTEGER);
|
vhdl_type integer(VHDL_TYPE_INTEGER);
|
||||||
ref->set_slice(vhd_off->cast(&integer));
|
ref->set_slice(vhd_off->cast(&integer));
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* VHDL code generation for LPM devices.
|
* VHDL code generation for LPM devices.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2008 Nick Gasson (nick@nickg.me.uk)
|
* Copyright (C) 2008-2009 Nick Gasson (nick@nickg.me.uk)
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
|
@ -48,10 +48,12 @@ static vhdl_expr *concat_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm)
|
||||||
vhdl_binop_expr *expr =
|
vhdl_binop_expr *expr =
|
||||||
new vhdl_binop_expr(VHDL_BINOP_CONCAT, result_type);
|
new vhdl_binop_expr(VHDL_BINOP_CONCAT, result_type);
|
||||||
|
|
||||||
for (int i = ivl_lpm_selects(lpm) - 1; i >= 0; i--) {
|
for (int i = ivl_lpm_size(lpm) - 1; i >= 0; i--) {
|
||||||
vhdl_expr *e = readable_ref(scope, ivl_lpm_data(lpm, i));
|
vhdl_expr *e = readable_ref(scope, ivl_lpm_data(lpm, i));
|
||||||
if (NULL == e)
|
if (NULL == e) {
|
||||||
|
delete expr;
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
expr->add_expr(e);
|
expr->add_expr(e);
|
||||||
}
|
}
|
||||||
|
|
@ -68,8 +70,10 @@ static vhdl_expr *binop_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm, vhdl_binop
|
||||||
|
|
||||||
for (int i = 0; i < 2; i++) {
|
for (int i = 0; i < 2; i++) {
|
||||||
vhdl_expr *e = readable_ref(scope, ivl_lpm_data(lpm, i));
|
vhdl_expr *e = readable_ref(scope, ivl_lpm_data(lpm, i));
|
||||||
if (NULL == e)
|
if (NULL == e) {
|
||||||
|
delete expr;
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
expr->add_expr(e->cast(result_type));
|
expr->add_expr(e->cast(result_type));
|
||||||
}
|
}
|
||||||
|
|
@ -95,8 +99,10 @@ static vhdl_expr *rel_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm, vhdl_binop_t
|
||||||
|
|
||||||
for (int i = 0; i < 2; i++) {
|
for (int i = 0; i < 2; i++) {
|
||||||
vhdl_expr *e = readable_ref(scope, ivl_lpm_data(lpm, i));
|
vhdl_expr *e = readable_ref(scope, ivl_lpm_data(lpm, i));
|
||||||
if (NULL == e)
|
if (NULL == e) {
|
||||||
|
delete expr;
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
expr->add_expr(e);
|
expr->add_expr(e);
|
||||||
}
|
}
|
||||||
|
|
@ -135,8 +141,10 @@ static vhdl_expr *ufunc_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm)
|
||||||
|
|
||||||
for (unsigned i = 0; i < ivl_lpm_size(lpm); i++) {
|
for (unsigned i = 0; i < ivl_lpm_size(lpm); i++) {
|
||||||
vhdl_var_ref *ref = readable_ref(scope, ivl_lpm_data(lpm, i));
|
vhdl_var_ref *ref = readable_ref(scope, ivl_lpm_data(lpm, i));
|
||||||
if (NULL == ref)
|
if (NULL == ref) {
|
||||||
|
delete fcall;
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
fcall->add_expr(ref);
|
fcall->add_expr(ref);
|
||||||
}
|
}
|
||||||
|
|
@ -195,8 +203,10 @@ static vhdl_expr *array_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm)
|
||||||
vhdl_type *atype = new vhdl_type(*adecl->get_type());
|
vhdl_type *atype = new vhdl_type(*adecl->get_type());
|
||||||
|
|
||||||
vhdl_expr *select = readable_ref(scope, ivl_lpm_select(lpm));
|
vhdl_expr *select = readable_ref(scope, ivl_lpm_select(lpm));
|
||||||
if (NULL == select)
|
if (NULL == select) {
|
||||||
|
delete atype;
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
vhdl_var_ref *ref = new vhdl_var_ref(renamed, atype);
|
vhdl_var_ref *ref = new vhdl_var_ref(renamed, atype);
|
||||||
vhdl_type integer(VHDL_TYPE_INTEGER);
|
vhdl_type integer(VHDL_TYPE_INTEGER);
|
||||||
|
|
|
||||||
|
|
@ -95,8 +95,13 @@ int draw_process(ivl_process_t proc, void *cd)
|
||||||
ivl_scope_tname(scope), ivl_process_file(proc),
|
ivl_scope_tname(scope), ivl_process_file(proc),
|
||||||
ivl_process_lineno(proc));
|
ivl_process_lineno(proc));
|
||||||
|
|
||||||
// A process should occur in a module scope, therefore it
|
// Skip over any generate and begin scopes until we find
|
||||||
// should have already been assigned a VHDL entity
|
// the module that contains them - this is where we will
|
||||||
|
// generate the process
|
||||||
|
while (ivl_scope_type(scope) == IVL_SCT_GENERATE
|
||||||
|
|| ivl_scope_type(scope) == IVL_SCT_BEGIN)
|
||||||
|
scope = ivl_scope_parent(scope);
|
||||||
|
|
||||||
assert(ivl_scope_type(scope) == IVL_SCT_MODULE);
|
assert(ivl_scope_type(scope) == IVL_SCT_MODULE);
|
||||||
vhdl_entity *ent = find_entity(scope);
|
vhdl_entity *ent = find_entity(scope);
|
||||||
assert(ent != NULL);
|
assert(ent != NULL);
|
||||||
|
|
|
||||||
|
|
@ -472,12 +472,50 @@ static void avoid_name_collision(string& name, vhdl_scope* scope)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Concatenate the expanded genvar values together to make a unique
|
||||||
|
// instance name
|
||||||
|
// This isn't ideal: it would be better to replace the Verilog
|
||||||
|
// generate with an equivalent VHDL generate, but this isn't possible
|
||||||
|
// with the current API
|
||||||
|
static string genvar_unique_suffix(ivl_scope_t scope)
|
||||||
|
{
|
||||||
|
ostringstream suffix;
|
||||||
|
while (scope && ivl_scope_type(scope) == IVL_SCT_GENERATE) {
|
||||||
|
for (unsigned i = 0; i < ivl_scope_params(scope); i++) {
|
||||||
|
ivl_parameter_t param = ivl_scope_param(scope, i);
|
||||||
|
ivl_expr_t e = ivl_parameter_expr(param);
|
||||||
|
|
||||||
|
if (ivl_expr_type(e) == IVL_EX_NUMBER) {
|
||||||
|
vhdl_expr* value = translate_expr(e);
|
||||||
|
assert(value);
|
||||||
|
|
||||||
|
value = value->cast(vhdl_type::integer());
|
||||||
|
|
||||||
|
suffix << "_" << ivl_parameter_basename(param);
|
||||||
|
value->emit(suffix, 0);
|
||||||
|
|
||||||
|
delete value;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
error("Only numeric genvars supported at the moment");
|
||||||
|
return "_ERROR"; // Never used
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
scope = ivl_scope_parent(scope);
|
||||||
|
}
|
||||||
|
|
||||||
|
return suffix.str();
|
||||||
|
}
|
||||||
|
|
||||||
// Declare a single signal in a scope
|
// Declare a single signal in a scope
|
||||||
static void declare_one_signal(vhdl_entity *ent, ivl_signal_t sig)
|
static void declare_one_signal(vhdl_entity *ent, ivl_signal_t sig,
|
||||||
|
ivl_scope_t scope)
|
||||||
{
|
{
|
||||||
remember_signal(sig, ent->get_arch()->get_scope());
|
remember_signal(sig, ent->get_arch()->get_scope());
|
||||||
|
|
||||||
string name(make_safe_name(sig));
|
string name(make_safe_name(sig));
|
||||||
|
name += genvar_unique_suffix(scope);
|
||||||
avoid_name_collision(name, ent->get_arch()->get_scope());
|
avoid_name_collision(name, ent->get_arch()->get_scope());
|
||||||
|
|
||||||
rename_signal(sig, name);
|
rename_signal(sig, name);
|
||||||
|
|
@ -586,14 +624,14 @@ static void declare_signals(vhdl_entity *ent, ivl_scope_t scope)
|
||||||
ivl_signal_t sig = ivl_scope_sig(scope, i);
|
ivl_signal_t sig = ivl_scope_sig(scope, i);
|
||||||
|
|
||||||
if (ivl_signal_port(sig) != IVL_SIP_NONE)
|
if (ivl_signal_port(sig) != IVL_SIP_NONE)
|
||||||
declare_one_signal(ent, sig);
|
declare_one_signal(ent, sig, scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < nsigs; i++) {
|
for (int i = 0; i < nsigs; i++) {
|
||||||
ivl_signal_t sig = ivl_scope_sig(scope, i);
|
ivl_signal_t sig = ivl_scope_sig(scope, i);
|
||||||
|
|
||||||
if (ivl_signal_port(sig) == IVL_SIP_NONE)
|
if (ivl_signal_port(sig) == IVL_SIP_NONE)
|
||||||
declare_one_signal(ent, sig);
|
declare_one_signal(ent, sig, scope);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -873,9 +911,6 @@ static int draw_skeleton_scope(ivl_scope_t scope, void *_unused)
|
||||||
case IVL_SCT_MODULE:
|
case IVL_SCT_MODULE:
|
||||||
create_skeleton_entity_for(scope, depth);
|
create_skeleton_entity_for(scope, depth);
|
||||||
break;
|
break;
|
||||||
case IVL_SCT_GENERATE:
|
|
||||||
error("No translation for generate statements yet");
|
|
||||||
return 1;
|
|
||||||
case IVL_SCT_FORK:
|
case IVL_SCT_FORK:
|
||||||
error("No translation for fork statements yet");
|
error("No translation for fork statements yet");
|
||||||
return 1;
|
return 1;
|
||||||
|
|
@ -901,6 +936,20 @@ static int draw_all_signals(ivl_scope_t scope, void *_parent)
|
||||||
|
|
||||||
declare_signals(ent, scope);
|
declare_signals(ent, scope);
|
||||||
}
|
}
|
||||||
|
else if (ivl_scope_type(scope) == IVL_SCT_GENERATE) {
|
||||||
|
// Because generate scopes don't appear in the
|
||||||
|
// output VHDL all their signals are added to the
|
||||||
|
// containing entity (after being uniqued)
|
||||||
|
|
||||||
|
ivl_scope_t parent = ivl_scope_parent(scope);
|
||||||
|
while (ivl_scope_type(parent) == IVL_SCT_GENERATE)
|
||||||
|
parent = ivl_scope_parent(scope);
|
||||||
|
|
||||||
|
vhdl_entity* ent = find_entity(parent);
|
||||||
|
assert(ent);
|
||||||
|
|
||||||
|
declare_signals(ent, scope);
|
||||||
|
}
|
||||||
|
|
||||||
return ivl_scope_children(scope, draw_all_signals, scope);
|
return ivl_scope_children(scope, draw_all_signals, scope);
|
||||||
}
|
}
|
||||||
|
|
@ -952,6 +1001,7 @@ static int draw_constant_drivers(ivl_scope_t scope, void *_parent)
|
||||||
j++) {
|
j++) {
|
||||||
// Make sure the nexus code is generated
|
// Make sure the nexus code is generated
|
||||||
ivl_nexus_t nex = ivl_signal_nex(sig, j);
|
ivl_nexus_t nex = ivl_signal_nex(sig, j);
|
||||||
|
if (!nex) continue; // skip virtual pins
|
||||||
seen_nexus(nex);
|
seen_nexus(nex);
|
||||||
|
|
||||||
nexus_private_t *priv =
|
nexus_private_t *priv =
|
||||||
|
|
@ -1031,6 +1081,10 @@ static int draw_hierarchy(ivl_scope_t scope, void *_parent)
|
||||||
if (ivl_scope_type(scope) == IVL_SCT_MODULE && _parent) {
|
if (ivl_scope_type(scope) == IVL_SCT_MODULE && _parent) {
|
||||||
ivl_scope_t parent = static_cast<ivl_scope_t>(_parent);
|
ivl_scope_t parent = static_cast<ivl_scope_t>(_parent);
|
||||||
|
|
||||||
|
// Skip over any containing generate scopes
|
||||||
|
while (ivl_scope_type(parent) == IVL_SCT_GENERATE)
|
||||||
|
parent = ivl_scope_parent(parent);
|
||||||
|
|
||||||
if (!is_default_scope_instance(parent))
|
if (!is_default_scope_instance(parent))
|
||||||
return 0; // Not generating code for the parent instance so
|
return 0; // Not generating code for the parent instance so
|
||||||
// don't generate for the child
|
// don't generate for the child
|
||||||
|
|
@ -1053,6 +1107,7 @@ static int draw_hierarchy(ivl_scope_t scope, void *_parent)
|
||||||
|
|
||||||
// And an instantiation statement
|
// And an instantiation statement
|
||||||
string inst_name(ivl_scope_basename(scope));
|
string inst_name(ivl_scope_basename(scope));
|
||||||
|
inst_name += genvar_unique_suffix(ivl_scope_parent(scope));
|
||||||
if (inst_name == ent->get_name() || parent_scope->have_declared(inst_name)) {
|
if (inst_name == ent->get_name() || parent_scope->have_declared(inst_name)) {
|
||||||
// Cannot have instance name the same as type in VHDL
|
// Cannot have instance name the same as type in VHDL
|
||||||
inst_name += "_Inst";
|
inst_name += "_Inst";
|
||||||
|
|
|
||||||
|
|
@ -170,8 +170,12 @@ vhdl_entity* find_entity(const string& name)
|
||||||
// name should be the same as the Verilog module type name.
|
// name should be the same as the Verilog module type name.
|
||||||
// Note that this will return NULL if no entity has been recorded
|
// Note that this will return NULL if no entity has been recorded
|
||||||
// for this scope type.
|
// for this scope type.
|
||||||
vhdl_entity* find_entity(const ivl_scope_t scope)
|
vhdl_entity* find_entity(ivl_scope_t scope)
|
||||||
{
|
{
|
||||||
|
// Skip over generate scopes
|
||||||
|
while (ivl_scope_type(scope) == IVL_SCT_GENERATE)
|
||||||
|
scope = ivl_scope_parent(scope);
|
||||||
|
|
||||||
assert(ivl_scope_type(scope) == IVL_SCT_MODULE);
|
assert(ivl_scope_type(scope) == IVL_SCT_MODULE);
|
||||||
|
|
||||||
scope_name_map_t::iterator it = g_scope_names.find(ivl_scope_tname(scope));
|
scope_name_map_t::iterator it = g_scope_names.find(ivl_scope_tname(scope));
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ ivl_signal_t find_signal_named(const std::string &name, const vhdl_scope *scope)
|
||||||
|
|
||||||
// Manage the set of VHDL entities
|
// Manage the set of VHDL entities
|
||||||
void remember_entity(vhdl_entity *ent, ivl_scope_t scope);
|
void remember_entity(vhdl_entity *ent, ivl_scope_t scope);
|
||||||
vhdl_entity* find_entity(const ivl_scope_t scope);
|
vhdl_entity* find_entity(ivl_scope_t scope);
|
||||||
vhdl_entity* find_entity(const std::string& name);
|
vhdl_entity* find_entity(const std::string& name);
|
||||||
void emit_all_entities(std::ostream& os, int max_depth);
|
void emit_all_entities(std::ostream& os, int max_depth);
|
||||||
void free_all_vhdl_objects();
|
void free_all_vhdl_objects();
|
||||||
|
|
|
||||||
|
|
@ -313,11 +313,11 @@ void make_assignment(vhdl_procedural *proc, stmt_container *container,
|
||||||
if (NULL == test)
|
if (NULL == test)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
vhdl_if_stmt *vhdif = new vhdl_if_stmt(test);
|
|
||||||
|
|
||||||
if (!check_valid_assignment(decl->assignment_type(), proc, stmt))
|
if (!check_valid_assignment(decl->assignment_type(), proc, stmt))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
vhdl_if_stmt *vhdif = new vhdl_if_stmt(test);
|
||||||
|
|
||||||
// True part
|
// True part
|
||||||
{
|
{
|
||||||
vhdl_abstract_assign_stmt *a =
|
vhdl_abstract_assign_stmt *a =
|
||||||
|
|
@ -552,7 +552,7 @@ static void get_nexuses_from_expr(ivl_expr_t expr, set<ivl_nexus_t> &out)
|
||||||
/*
|
/*
|
||||||
* Attempt to identify common forms of wait statements and produce
|
* Attempt to identify common forms of wait statements and produce
|
||||||
* more idiomatic VHDL than would be produced by the generic
|
* more idiomatic VHDL than would be produced by the generic
|
||||||
* draw_wait funciton. The main application of this is a input to
|
* draw_wait function. The main application of this is a input to
|
||||||
* synthesis tools that don't synthesise the full VHDL language.
|
* synthesis tools that don't synthesise the full VHDL language.
|
||||||
* If none of these patterns are matched, the function returns false
|
* If none of these patterns are matched, the function returns false
|
||||||
* and the default draw_wait is used.
|
* and the default draw_wait is used.
|
||||||
|
|
@ -1342,6 +1342,7 @@ int draw_casezx(vhdl_procedural *proc, stmt_container *container,
|
||||||
"expression labels can be translated to VHDL",
|
"expression labels can be translated to VHDL",
|
||||||
ivl_stmt_file(stmt), ivl_stmt_lineno(stmt),
|
ivl_stmt_file(stmt), ivl_stmt_lineno(stmt),
|
||||||
(is_casez ? "z" : "x"));
|
(is_casez ? "z" : "x"));
|
||||||
|
delete all;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2008 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2002-2009 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -19,9 +19,6 @@
|
||||||
|
|
||||||
# include "vvp_priv.h"
|
# include "vvp_priv.h"
|
||||||
# include <assert.h>
|
# include <assert.h>
|
||||||
#ifdef HAVE_MALLOC_H
|
|
||||||
# include <malloc.h>
|
|
||||||
#endif
|
|
||||||
# include <stdlib.h>
|
# include <stdlib.h>
|
||||||
# include <string.h>
|
# include <string.h>
|
||||||
|
|
||||||
|
|
@ -51,12 +48,20 @@ static void draw_lpm_mux_ab(ivl_lpm_t net, const char*muxz)
|
||||||
if (number_is_immediate(d_rise, 64, 0) &&
|
if (number_is_immediate(d_rise, 64, 0) &&
|
||||||
number_is_immediate(d_fall, 64, 0) &&
|
number_is_immediate(d_fall, 64, 0) &&
|
||||||
number_is_immediate(d_decay, 64, 0)) {
|
number_is_immediate(d_decay, 64, 0)) {
|
||||||
|
|
||||||
|
assert( ! number_is_unknown(d_rise));
|
||||||
|
assert( ! number_is_unknown(d_fall));
|
||||||
|
assert( ! number_is_unknown(d_decay));
|
||||||
|
|
||||||
fprintf(vvp_out, "L_%p .delay (%lu,%lu,%lu) L_%p/d;\n",
|
fprintf(vvp_out, "L_%p .delay (%lu,%lu,%lu) L_%p/d;\n",
|
||||||
net, get_number_immediate(d_rise),
|
net, get_number_immediate(d_rise),
|
||||||
get_number_immediate(d_rise),
|
get_number_immediate(d_fall),
|
||||||
get_number_immediate(d_rise), net);
|
get_number_immediate(d_decay), net);
|
||||||
} else {
|
} else {
|
||||||
ivl_signal_t sig;
|
ivl_signal_t sig;
|
||||||
|
// We do not currently support calculating the decay from
|
||||||
|
// the rise and fall variable delays.
|
||||||
|
assert(d_decay != 0);
|
||||||
assert(ivl_expr_type(d_rise) == IVL_EX_SIGNAL);
|
assert(ivl_expr_type(d_rise) == IVL_EX_SIGNAL);
|
||||||
assert(ivl_expr_type(d_fall) == IVL_EX_SIGNAL);
|
assert(ivl_expr_type(d_fall) == IVL_EX_SIGNAL);
|
||||||
assert(ivl_expr_type(d_decay) == IVL_EX_SIGNAL);
|
assert(ivl_expr_type(d_decay) == IVL_EX_SIGNAL);
|
||||||
|
|
|
||||||
|
|
@ -388,14 +388,21 @@ static char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr)
|
||||||
number_is_immediate(d_fall, 64, 0) &&
|
number_is_immediate(d_fall, 64, 0) &&
|
||||||
number_is_immediate(d_decay, 64, 0)) {
|
number_is_immediate(d_decay, 64, 0)) {
|
||||||
|
|
||||||
|
assert(! number_is_unknown(d_rise));
|
||||||
|
assert(! number_is_unknown(d_fall));
|
||||||
|
assert(! number_is_unknown(d_decay));
|
||||||
|
|
||||||
fprintf(vvp_out, "L_%p .delay "
|
fprintf(vvp_out, "L_%p .delay "
|
||||||
"(%" PRIu64 ",%" PRIu64 ",%" PRIu64 ") L_%p/d;\n",
|
"(%" PRIu64 ",%" PRIu64 ",%" PRIu64 ") L_%p/d;\n",
|
||||||
cptr, get_number_immediate64(d_rise),
|
cptr, get_number_immediate64(d_rise),
|
||||||
get_number_immediate64(d_rise),
|
get_number_immediate64(d_fall),
|
||||||
get_number_immediate64(d_rise), cptr);
|
get_number_immediate64(d_decay), cptr);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
ivl_signal_t sig;
|
ivl_signal_t sig;
|
||||||
|
// We do not currently support calculating the decay
|
||||||
|
// from the rise and fall variable delays.
|
||||||
|
assert(d_decay != 0);
|
||||||
assert(ivl_expr_type(d_rise) == IVL_EX_SIGNAL);
|
assert(ivl_expr_type(d_rise) == IVL_EX_SIGNAL);
|
||||||
assert(ivl_expr_type(d_fall) == IVL_EX_SIGNAL);
|
assert(ivl_expr_type(d_fall) == IVL_EX_SIGNAL);
|
||||||
assert(ivl_expr_type(d_decay) == IVL_EX_SIGNAL);
|
assert(ivl_expr_type(d_decay) == IVL_EX_SIGNAL);
|
||||||
|
|
@ -502,6 +509,16 @@ static char* draw_island_port(ivl_island_t island,
|
||||||
/* Omit LPMPART_BI device pin-data(0) drivers. */
|
/* Omit LPMPART_BI device pin-data(0) drivers. */
|
||||||
# define OMIT_PART_BI_DATA 0x0001
|
# define OMIT_PART_BI_DATA 0x0001
|
||||||
|
|
||||||
|
static ivl_nexus_ptr_t *drivers = 0x0;
|
||||||
|
static unsigned adrivers = 0;
|
||||||
|
|
||||||
|
void EOC_cleanup_drivers()
|
||||||
|
{
|
||||||
|
free(drivers);
|
||||||
|
drivers = NULL;
|
||||||
|
adrivers = 0;
|
||||||
|
}
|
||||||
|
|
||||||
char* draw_net_input_x(ivl_nexus_t nex,
|
char* draw_net_input_x(ivl_nexus_t nex,
|
||||||
ivl_nexus_ptr_t omit_ptr, int omit_flags,
|
ivl_nexus_ptr_t omit_ptr, int omit_flags,
|
||||||
struct vvp_nexus_data*nex_data)
|
struct vvp_nexus_data*nex_data)
|
||||||
|
|
@ -512,8 +529,6 @@ char* draw_net_input_x(ivl_nexus_t nex,
|
||||||
unsigned idx;
|
unsigned idx;
|
||||||
int level;
|
int level;
|
||||||
unsigned ndrivers = 0;
|
unsigned ndrivers = 0;
|
||||||
static ivl_nexus_ptr_t *drivers = 0x0;
|
|
||||||
static unsigned adrivers = 0;
|
|
||||||
|
|
||||||
const char*resolv_type;
|
const char*resolv_type;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -109,6 +109,7 @@ static int get_vpi_taskfunc_signal_arg(struct args_info *result,
|
||||||
if (word_ex) {
|
if (word_ex) {
|
||||||
/* Some array select have been evaluated. */
|
/* Some array select have been evaluated. */
|
||||||
if (number_is_immediate(word_ex,IMM_WID, 0)) {
|
if (number_is_immediate(word_ex,IMM_WID, 0)) {
|
||||||
|
assert(! number_is_unknown(word_ex));
|
||||||
use_word = get_number_immediate(word_ex);
|
use_word = get_number_immediate(word_ex);
|
||||||
word_ex = 0;
|
word_ex = 0;
|
||||||
}
|
}
|
||||||
|
|
@ -125,11 +126,14 @@ static int get_vpi_taskfunc_signal_arg(struct args_info *result,
|
||||||
Create the right code to handle it. */
|
Create the right code to handle it. */
|
||||||
ivl_signal_t sig = ivl_expr_signal(expr);
|
ivl_signal_t sig = ivl_expr_signal(expr);
|
||||||
unsigned use_word = 0;
|
unsigned use_word = 0;
|
||||||
|
unsigned use_word_defined = 0;
|
||||||
ivl_expr_t word_ex = ivl_expr_oper1(expr);
|
ivl_expr_t word_ex = ivl_expr_oper1(expr);
|
||||||
if (word_ex) {
|
if (word_ex) {
|
||||||
/* Some array select have been evaluated. */
|
/* Some array select have been evaluated. */
|
||||||
if (number_is_immediate(word_ex, IMM_WID, 0)) {
|
if (number_is_immediate(word_ex, IMM_WID, 0)) {
|
||||||
|
assert(! number_is_unknown(word_ex));
|
||||||
use_word = get_number_immediate(word_ex);
|
use_word = get_number_immediate(word_ex);
|
||||||
|
use_word_defined = 1;
|
||||||
word_ex = 0;
|
word_ex = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -156,6 +160,7 @@ static int get_vpi_taskfunc_signal_arg(struct args_info *result,
|
||||||
result->vec = av;
|
result->vec = av;
|
||||||
result->vec_flag = 1;
|
result->vec_flag = 1;
|
||||||
} else {
|
} else {
|
||||||
|
assert(use_word_defined);
|
||||||
snprintf(buffer, sizeof buffer, "&A<v%p, %u>",
|
snprintf(buffer, sizeof buffer, "&A<v%p, %u>",
|
||||||
sig, use_word);
|
sig, use_word);
|
||||||
}
|
}
|
||||||
|
|
@ -182,6 +187,7 @@ static int get_vpi_taskfunc_signal_arg(struct args_info *result,
|
||||||
|
|
||||||
/* This is a constant bit/part select. */
|
/* This is a constant bit/part select. */
|
||||||
if (number_is_immediate(bexpr, 64, 1)) {
|
if (number_is_immediate(bexpr, 64, 1)) {
|
||||||
|
assert(! number_is_unknown(bexpr));
|
||||||
snprintf(buffer, sizeof buffer, "&PV<v%p_0, %ld, %u>",
|
snprintf(buffer, sizeof buffer, "&PV<v%p_0, %ld, %u>",
|
||||||
ivl_expr_signal(vexpr),
|
ivl_expr_signal(vexpr),
|
||||||
get_number_immediate(bexpr),
|
get_number_immediate(bexpr),
|
||||||
|
|
@ -203,9 +209,19 @@ static int get_vpi_taskfunc_signal_arg(struct args_info *result,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Fallback case: evaluate the expression. */
|
/* Fallback case: evaluate the expression. */
|
||||||
struct vector_info rv;
|
struct vector_info rv;
|
||||||
rv = draw_eval_expr(bexpr, STUFF_OK_XZ);
|
rv = draw_eval_expr(bexpr, STUFF_OK_XZ);
|
||||||
|
/* We need to enhance &PV<> to support a signed index. */
|
||||||
|
if (ivl_expr_signed(bexpr) &&
|
||||||
|
(ivl_expr_width(bexpr) < 8*sizeof(int))) {
|
||||||
|
fprintf(stderr, "%s:%u: tgt-vvp warning: V0.9 may give "
|
||||||
|
"incorrect results for a select with a "
|
||||||
|
"signed index less than %zu bits.\n",
|
||||||
|
ivl_expr_file(expr),
|
||||||
|
ivl_expr_lineno(expr),
|
||||||
|
8*sizeof(int));
|
||||||
|
}
|
||||||
snprintf(buffer, sizeof buffer, "&PV<v%p_0, %u %u, %u>",
|
snprintf(buffer, sizeof buffer, "&PV<v%p_0, %u %u, %u>",
|
||||||
ivl_expr_signal(vexpr),
|
ivl_expr_signal(vexpr),
|
||||||
rv.base, rv.wid,
|
rv.base, rv.wid,
|
||||||
|
|
|
||||||
|
|
@ -174,6 +174,12 @@ static void eval_logic_into_integer(ivl_expr_t expr, unsigned ix)
|
||||||
case IVL_EX_ULONG:
|
case IVL_EX_ULONG:
|
||||||
{
|
{
|
||||||
assert(number_is_immediate(expr, IMM_WID, 1));
|
assert(number_is_immediate(expr, IMM_WID, 1));
|
||||||
|
if (number_is_unknown(expr)) {
|
||||||
|
/* We are loading a 'bx so mimic %ix/get. */
|
||||||
|
fprintf(vvp_out, " %%ix/load %u, 0, 0;\n", ix);
|
||||||
|
fprintf(vvp_out, " %%mov 4, 1, 1;\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
long imm = get_number_immediate(expr);
|
long imm = get_number_immediate(expr);
|
||||||
if (imm >= 0) {
|
if (imm >= 0) {
|
||||||
fprintf(vvp_out, " %%ix/load %u, %ld, 0;\n", ix, imm);
|
fprintf(vvp_out, " %%ix/load %u, %ld, 0;\n", ix, imm);
|
||||||
|
|
@ -192,6 +198,7 @@ static void eval_logic_into_integer(ivl_expr_t expr, unsigned ix)
|
||||||
unsigned word = 0;
|
unsigned word = 0;
|
||||||
if (ivl_signal_dimensions(sig) > 0) {
|
if (ivl_signal_dimensions(sig) > 0) {
|
||||||
ivl_expr_t ixe;
|
ivl_expr_t ixe;
|
||||||
|
char*type = ivl_expr_signed(expr) ? "/s" : "";
|
||||||
|
|
||||||
/* Detect the special case that this is a
|
/* Detect the special case that this is a
|
||||||
variable array. In this case, the ix/getv
|
variable array. In this case, the ix/getv
|
||||||
|
|
@ -199,20 +206,21 @@ static void eval_logic_into_integer(ivl_expr_t expr, unsigned ix)
|
||||||
if (ivl_signal_type(sig) == IVL_SIT_REG) {
|
if (ivl_signal_type(sig) == IVL_SIT_REG) {
|
||||||
struct vector_info rv;
|
struct vector_info rv;
|
||||||
rv = draw_eval_expr(expr, 0);
|
rv = draw_eval_expr(expr, 0);
|
||||||
fprintf(vvp_out, " %%ix/get %u, %u, %u;\n",
|
fprintf(vvp_out, " %%ix/get%s %u, %u, %u;\n",
|
||||||
ix, rv.base, rv.wid);
|
type, ix, rv.base, rv.wid);
|
||||||
clr_vector(rv);
|
clr_vector(rv);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ixe = ivl_expr_oper1(expr);
|
ixe = ivl_expr_oper1(expr);
|
||||||
if (number_is_immediate(ixe, IMM_WID, 0))
|
if (number_is_immediate(ixe, IMM_WID, 0)) {
|
||||||
|
assert(! number_is_unknown(ixe));
|
||||||
word = get_number_immediate(ixe);
|
word = get_number_immediate(ixe);
|
||||||
else {
|
} else {
|
||||||
struct vector_info rv;
|
struct vector_info rv;
|
||||||
rv = draw_eval_expr(expr, 0);
|
rv = draw_eval_expr(expr, 0);
|
||||||
fprintf(vvp_out, " %%ix/get %u, %u, %u;\n",
|
fprintf(vvp_out, " %%ix/get%s %u, %u, %u;\n",
|
||||||
ix, rv.base, rv.wid);
|
type, ix, rv.base, rv.wid);
|
||||||
clr_vector(rv);
|
clr_vector(rv);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -226,8 +234,14 @@ static void eval_logic_into_integer(ivl_expr_t expr, unsigned ix)
|
||||||
default: {
|
default: {
|
||||||
struct vector_info rv;
|
struct vector_info rv;
|
||||||
rv = draw_eval_expr(expr, 0);
|
rv = draw_eval_expr(expr, 0);
|
||||||
fprintf(vvp_out, " %%ix/get %u, %u, %u;\n",
|
/* Is this a signed expression? */
|
||||||
ix, rv.base, rv.wid);
|
if (ivl_expr_signed(expr)) {
|
||||||
|
fprintf(vvp_out, " %%ix/get/s %u, %u, %u;\n",
|
||||||
|
ix, rv.base, rv.wid);
|
||||||
|
} else {
|
||||||
|
fprintf(vvp_out, " %%ix/get %u, %u, %u;\n",
|
||||||
|
ix, rv.base, rv.wid);
|
||||||
|
}
|
||||||
clr_vector(rv);
|
clr_vector(rv);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -274,7 +288,10 @@ static struct vector_info draw_eq_immediate(ivl_expr_t exp, unsigned ewid,
|
||||||
{
|
{
|
||||||
unsigned wid;
|
unsigned wid;
|
||||||
struct vector_info lv;
|
struct vector_info lv;
|
||||||
unsigned long imm = get_number_immediate(re);
|
unsigned long imm;
|
||||||
|
assert(number_is_immediate(re, IMM_WID, 0));
|
||||||
|
assert(! number_is_unknown(re));
|
||||||
|
imm = get_number_immediate(re);
|
||||||
|
|
||||||
wid = ivl_expr_width(le);
|
wid = ivl_expr_width(le);
|
||||||
lv = draw_eval_expr_wid(le, wid, stuff_ok_flag);
|
lv = draw_eval_expr_wid(le, wid, stuff_ok_flag);
|
||||||
|
|
@ -991,6 +1008,8 @@ static struct vector_info draw_logic_immediate(ivl_expr_t exp,
|
||||||
unsigned wid)
|
unsigned wid)
|
||||||
{
|
{
|
||||||
struct vector_info lv = draw_eval_expr_wid(le, wid, STUFF_OK_XZ);
|
struct vector_info lv = draw_eval_expr_wid(le, wid, STUFF_OK_XZ);
|
||||||
|
assert(number_is_immediate(re, IMM_WID, 0));
|
||||||
|
assert(! number_is_unknown(re));
|
||||||
unsigned long imm = get_number_immediate(re);
|
unsigned long imm = get_number_immediate(re);
|
||||||
|
|
||||||
assert(lv.base >= 4);
|
assert(lv.base >= 4);
|
||||||
|
|
@ -1241,8 +1260,10 @@ static struct vector_info draw_load_add_immediate(ivl_expr_t le,
|
||||||
int signed_flag)
|
int signed_flag)
|
||||||
{
|
{
|
||||||
struct vector_info lv;
|
struct vector_info lv;
|
||||||
long imm = get_number_immediate(re);
|
long imm;
|
||||||
|
assert(! number_is_unknown(re));
|
||||||
assert(number_is_immediate(re, IMM_WID, 1));
|
assert(number_is_immediate(re, IMM_WID, 1));
|
||||||
|
imm = get_number_immediate(re);
|
||||||
lv.base = allocate_vector(wid);
|
lv.base = allocate_vector(wid);
|
||||||
lv.wid = wid;
|
lv.wid = wid;
|
||||||
if (lv.base == 0) {
|
if (lv.base == 0) {
|
||||||
|
|
@ -1270,6 +1291,8 @@ static struct vector_info draw_add_immediate(ivl_expr_t le,
|
||||||
lv = draw_eval_expr_wid(le, wid, STUFF_OK_XZ);
|
lv = draw_eval_expr_wid(le, wid, STUFF_OK_XZ);
|
||||||
assert(lv.wid == wid);
|
assert(lv.wid == wid);
|
||||||
|
|
||||||
|
assert(! number_is_unknown(re));
|
||||||
|
assert(number_is_immediate(re, IMM_WID, 0));
|
||||||
imm = get_number_immediate(re);
|
imm = get_number_immediate(re);
|
||||||
|
|
||||||
/* This shouldn't generally happen, because the elaborator
|
/* This shouldn't generally happen, because the elaborator
|
||||||
|
|
@ -1308,7 +1331,7 @@ static struct vector_info draw_add_immediate(ivl_expr_t le,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2: /* Left expression is X or Z */
|
case 2: /* Left expression is 'bx or 'bz */
|
||||||
case 3:
|
case 3:
|
||||||
lv.base = 2;
|
lv.base = 2;
|
||||||
break;
|
break;
|
||||||
|
|
@ -1335,6 +1358,8 @@ static struct vector_info draw_sub_immediate(ivl_expr_t le,
|
||||||
lv = draw_eval_expr_wid(le, wid, STUFF_OK_XZ);
|
lv = draw_eval_expr_wid(le, wid, STUFF_OK_XZ);
|
||||||
assert(lv.wid == wid);
|
assert(lv.wid == wid);
|
||||||
|
|
||||||
|
assert(! number_is_unknown(re));
|
||||||
|
assert(number_is_immediate(re, IMM_WID, 0));
|
||||||
imm = get_number_immediate(re);
|
imm = get_number_immediate(re);
|
||||||
if (imm == 0)
|
if (imm == 0)
|
||||||
return lv;
|
return lv;
|
||||||
|
|
@ -1379,6 +1404,8 @@ static struct vector_info draw_mul_immediate(ivl_expr_t le,
|
||||||
lv = draw_eval_expr_wid(le, wid, STUFF_OK_XZ);
|
lv = draw_eval_expr_wid(le, wid, STUFF_OK_XZ);
|
||||||
assert(lv.wid == wid);
|
assert(lv.wid == wid);
|
||||||
|
|
||||||
|
assert(! number_is_unknown(re));
|
||||||
|
assert(number_is_immediate(re, IMM_WID, 0));
|
||||||
imm = get_number_immediate(re);
|
imm = get_number_immediate(re);
|
||||||
if (imm == 0)
|
if (imm == 0)
|
||||||
return lv;
|
return lv;
|
||||||
|
|
@ -1396,9 +1423,9 @@ static struct vector_info draw_binary_expr_arith(ivl_expr_t exp, unsigned wid)
|
||||||
struct vector_info lv;
|
struct vector_info lv;
|
||||||
struct vector_info rv;
|
struct vector_info rv;
|
||||||
|
|
||||||
const char*sign_string = ivl_expr_signed(le) && ivl_expr_signed(re)? "/s" : "";
|
int signed_flag = ivl_expr_signed(le) && ivl_expr_signed(re) ? 1 : 0;
|
||||||
|
const char*sign_string = signed_flag ? "/s" : "";
|
||||||
|
|
||||||
int signed_flag = ivl_expr_signed(exp)? 1 : 0;
|
|
||||||
|
|
||||||
if ((ivl_expr_opcode(exp) == '+')
|
if ((ivl_expr_opcode(exp) == '+')
|
||||||
&& (ivl_expr_type(le) == IVL_EX_SIGNAL)
|
&& (ivl_expr_type(le) == IVL_EX_SIGNAL)
|
||||||
|
|
@ -1619,82 +1646,118 @@ static struct vector_info draw_binary_expr(ivl_expr_t exp,
|
||||||
static struct vector_info draw_concat_expr(ivl_expr_t exp, unsigned wid,
|
static struct vector_info draw_concat_expr(ivl_expr_t exp, unsigned wid,
|
||||||
int stuff_ok_flag)
|
int stuff_ok_flag)
|
||||||
{
|
{
|
||||||
unsigned off, rep;
|
unsigned off, rep, expr_wid, concat_wid, num_sube, idx;
|
||||||
struct vector_info res;
|
struct vector_info res;
|
||||||
|
|
||||||
int alloc_exclusive = (stuff_ok_flag&STUFF_OK_RO) ? 0 : 1;
|
int alloc_exclusive = (stuff_ok_flag&STUFF_OK_RO) ? 0 : 1;
|
||||||
|
|
||||||
/* Allocate a vector to hold the result. */
|
/* Find out how wide the base concatenation expression is. */
|
||||||
res.base = allocate_vector(wid);
|
num_sube = ivl_expr_parms(exp);
|
||||||
res.wid = wid;
|
expr_wid = 0;
|
||||||
if (res.base == 0) {
|
for (idx = 0 ; idx < num_sube; idx += 1) {
|
||||||
fprintf(stderr, "%s:%u: vvp.tgt error: "
|
expr_wid += ivl_expr_width(ivl_expr_parm(exp, idx));
|
||||||
"Unable to allocate %u thread bits "
|
|
||||||
"for result of concatenation.\n",
|
|
||||||
ivl_expr_file(exp), ivl_expr_lineno(exp), wid);
|
|
||||||
vvp_errors += 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the repeat count. This must be a constant that has been
|
/* Get the repeat count. This must be a constant that has been
|
||||||
evaluated at compile time. The operands will be repeated to
|
evaluated at compile time. The operands will be repeated to
|
||||||
form the result. */
|
form the result. */
|
||||||
rep = ivl_expr_repeat(exp);
|
rep = ivl_expr_repeat(exp);
|
||||||
off = 0;
|
|
||||||
|
|
||||||
while (rep > 0) {
|
/* Allocate a vector to hold the result. */
|
||||||
|
if (rep == 0) {
|
||||||
|
/* If the replication is zero we need to allocate temporary
|
||||||
|
* space to build the concatenation. */
|
||||||
|
res.base = allocate_vector(expr_wid);
|
||||||
|
res.wid = expr_wid;
|
||||||
|
} else {
|
||||||
|
res.base = allocate_vector(wid);
|
||||||
|
res.wid = wid;
|
||||||
|
}
|
||||||
|
if (res.base == 0) {
|
||||||
|
fprintf(stderr, "%s:%u: vvp.tgt error: "
|
||||||
|
"Unable to allocate %u thread bits "
|
||||||
|
"for result of concatenation.\n",
|
||||||
|
ivl_expr_file(exp), ivl_expr_lineno(exp),
|
||||||
|
rep ? wid : expr_wid);
|
||||||
|
vvp_errors += 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Each repeat, evaluate the sub-expressions, from lsb
|
/* If the result is the right size we can just build this in place. */
|
||||||
to msb, and copy each into the result vector. The
|
concat_wid = rep*expr_wid;
|
||||||
expressions are arranged in the concatenation from
|
if (concat_wid <= wid) {
|
||||||
MSB to LSB, to go through them backwards.
|
off = 0;
|
||||||
|
/* Evaluate the base expression. */
|
||||||
Abort the loop if the result vector gets filled up. */
|
for (idx = num_sube; idx > 0; idx -= 1) {
|
||||||
|
|
||||||
unsigned idx = ivl_expr_parms(exp);
|
|
||||||
while ((idx > 0) && (off < wid)) {
|
|
||||||
ivl_expr_t arg = ivl_expr_parm(exp, idx-1);
|
ivl_expr_t arg = ivl_expr_parm(exp, idx-1);
|
||||||
unsigned awid = ivl_expr_width(arg);
|
unsigned awid = ivl_expr_width(arg);
|
||||||
|
|
||||||
unsigned trans;
|
|
||||||
struct vector_info avec;
|
struct vector_info avec;
|
||||||
|
|
||||||
|
assert(awid+off <= expr_wid);
|
||||||
|
|
||||||
/* Try to locate the subexpression in the
|
/* Try to locate the subexpression in the
|
||||||
lookaside map. */
|
* lookaside map and use it when available. */
|
||||||
avec.base = allocate_vector_exp(arg, awid, alloc_exclusive);
|
avec.base = allocate_vector_exp(arg, awid, alloc_exclusive);
|
||||||
avec.wid = awid;
|
avec.wid = awid;
|
||||||
|
|
||||||
trans = awid;
|
|
||||||
if ((off + awid) > wid)
|
|
||||||
trans = wid - off;
|
|
||||||
|
|
||||||
if (avec.base != 0) {
|
if (avec.base != 0) {
|
||||||
assert(awid == avec.wid);
|
assert(awid == avec.wid);
|
||||||
|
fprintf(vvp_out, " %%mov %u, %u, %u; Reuse "
|
||||||
fprintf(vvp_out, " %%mov %u, %u, %u; Reuse calculated expression\n",
|
"calculated expression.\n",
|
||||||
res.base+off,
|
res.base+off, avec.base, awid);
|
||||||
avec.base, trans);
|
clr_vector(avec);
|
||||||
clr_vector(avec);
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
struct vector_info dest;
|
struct vector_info dest;
|
||||||
|
|
||||||
dest.base = res.base+off;
|
dest.base = res.base+off;
|
||||||
dest.wid = trans;
|
dest.wid = awid;
|
||||||
draw_eval_expr_dest(arg, dest, 0);
|
draw_eval_expr_dest(arg, dest, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
off += awid;
|
||||||
idx -= 1;
|
|
||||||
off += trans;
|
|
||||||
assert(off <= wid);
|
|
||||||
}
|
}
|
||||||
rep -= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Pad the result with 0, if necessary. */
|
/* Now repeat the expression as needed. */
|
||||||
if (off < wid) {
|
if (rep != 0) {
|
||||||
fprintf(vvp_out, " %%mov %u, 0, %u;\n",
|
rep -= 1;
|
||||||
res.base+off, wid-off);
|
} else {
|
||||||
|
/* Clear the temporary space and return nothing.
|
||||||
|
* This will be caught in draw_eval_expr_dest()
|
||||||
|
* and dropped. */
|
||||||
|
clr_vector(res);
|
||||||
|
res.base = 0;
|
||||||
|
res.wid = 0;
|
||||||
|
}
|
||||||
|
while (rep > 0) {
|
||||||
|
fprintf(vvp_out, " %%mov %u, %u, %u; Repetition %u\n",
|
||||||
|
res.base+expr_wid*rep, res.base, expr_wid,
|
||||||
|
rep+1);
|
||||||
|
rep -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Pad the expression when needed. */
|
||||||
|
if (wid > concat_wid) {
|
||||||
|
/* We can get a signed concatenation with $signed({...}). */
|
||||||
|
if (ivl_expr_signed(exp)) {
|
||||||
|
unsigned base = res.base+concat_wid-1;
|
||||||
|
for (idx = 1; idx <= wid-concat_wid; idx += 1) {
|
||||||
|
fprintf(vvp_out, " %%mov %u, %u, 1;\n",
|
||||||
|
base+idx, base);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fprintf(vvp_out, " %%mov %u, 0, %u;\n",
|
||||||
|
res.base+concat_wid, wid-concat_wid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* The concatenation is too big for the result so draw it
|
||||||
|
* at full width and then copy the bits that are needed. */
|
||||||
|
struct vector_info full_res;
|
||||||
|
full_res = draw_concat_expr(exp, concat_wid, stuff_ok_flag);
|
||||||
|
assert(full_res.base);
|
||||||
|
|
||||||
|
fprintf(vvp_out, " %%mov %u, %u, %u;\n", res.base,
|
||||||
|
full_res.base, wid);
|
||||||
|
clr_vector(full_res);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Save the accumulated result in the lookaside map. */
|
/* Save the accumulated result in the lookaside map. */
|
||||||
|
|
@ -1853,7 +1916,7 @@ static struct vector_info draw_number_expr(ivl_expr_t exp, unsigned wid)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This little helper function generates the instructions to pad a
|
* This little helper function generates the instructions to pad a
|
||||||
* vector in place. It is assumed that the calling functio has set up
|
* vector in place. It is assumed that the calling function has set up
|
||||||
* the first sub_sidth bits of the dest vector, and the signed_flag is
|
* the first sub_sidth bits of the dest vector, and the signed_flag is
|
||||||
* true if the extension is to be signed.
|
* true if the extension is to be signed.
|
||||||
*/
|
*/
|
||||||
|
|
@ -2217,7 +2280,7 @@ static struct vector_info draw_select_array(ivl_expr_t sube,
|
||||||
unsigned bit_width,
|
unsigned bit_width,
|
||||||
unsigned wid)
|
unsigned wid)
|
||||||
{
|
{
|
||||||
unsigned idx;
|
unsigned idx, label;
|
||||||
ivl_signal_t sig = ivl_expr_signal(sube);
|
ivl_signal_t sig = ivl_expr_signal(sube);
|
||||||
/* unsigned sig_wid = ivl_expr_width(sube); */
|
/* unsigned sig_wid = ivl_expr_width(sube); */
|
||||||
ivl_expr_t ix = ivl_expr_oper1(sube);
|
ivl_expr_t ix = ivl_expr_oper1(sube);
|
||||||
|
|
@ -2227,7 +2290,18 @@ static struct vector_info draw_select_array(ivl_expr_t sube,
|
||||||
|
|
||||||
shiv = draw_eval_expr(bit_idx, STUFF_OK_XZ|STUFF_OK_RO);
|
shiv = draw_eval_expr(bit_idx, STUFF_OK_XZ|STUFF_OK_RO);
|
||||||
draw_eval_expr_into_integer(ix, 3);
|
draw_eval_expr_into_integer(ix, 3);
|
||||||
fprintf(vvp_out, " %%ix/get 0, %u, %u;\n", shiv.base, shiv.wid);
|
label = local_count++;
|
||||||
|
/* We can safely skip the bit index load below if the array word
|
||||||
|
* index is undefined. We need to do this so that the bit index
|
||||||
|
* load does not reset bit 4 to zero by loading a defined value. */
|
||||||
|
fprintf(vvp_out, " %%jmp/1 T_%d.%d, 4;\n", thread_count, label);
|
||||||
|
if (ivl_expr_signed(bit_idx)) {
|
||||||
|
fprintf(vvp_out, " %%ix/get/s 0, %u, %u;\n", shiv.base,
|
||||||
|
shiv.wid);
|
||||||
|
} else {
|
||||||
|
fprintf(vvp_out, " %%ix/get 0, %u, %u;\n", shiv.base, shiv.wid);
|
||||||
|
}
|
||||||
|
fprintf(vvp_out, "T_%d.%d ;\n", thread_count, label);
|
||||||
if (shiv.base >= 8)
|
if (shiv.base >= 8)
|
||||||
clr_vector(shiv);
|
clr_vector(shiv);
|
||||||
|
|
||||||
|
|
@ -2258,7 +2332,7 @@ static struct vector_info draw_select_signal(ivl_expr_t sube,
|
||||||
|
|
||||||
/* Use this word of the signal. */
|
/* Use this word of the signal. */
|
||||||
unsigned use_word = 0;
|
unsigned use_word = 0;
|
||||||
unsigned use_wid;
|
unsigned use_wid, lab_x, lab_end;
|
||||||
|
|
||||||
/* If this is an access to an array, try to get the index as a
|
/* If this is an access to an array, try to get the index as a
|
||||||
constant. If it is (and the array is not a reg array then
|
constant. If it is (and the array is not a reg array then
|
||||||
|
|
@ -2275,6 +2349,7 @@ static struct vector_info draw_select_signal(ivl_expr_t sube,
|
||||||
|
|
||||||
/* The index is constant, so we can return to direct
|
/* The index is constant, so we can return to direct
|
||||||
readout with the specific word selected. */
|
readout with the specific word selected. */
|
||||||
|
assert(! number_is_unknown(ix));
|
||||||
use_word = get_number_immediate(ix);
|
use_word = get_number_immediate(ix);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2282,6 +2357,7 @@ static struct vector_info draw_select_signal(ivl_expr_t sube,
|
||||||
the signal (or the entire width). Just load the early bits
|
the signal (or the entire width). Just load the early bits
|
||||||
in one go. */
|
in one go. */
|
||||||
if (number_is_immediate(bit_idx, 32, 0)
|
if (number_is_immediate(bit_idx, 32, 0)
|
||||||
|
&& !number_is_unknown(bit_idx)
|
||||||
&& get_number_immediate(bit_idx) == 0
|
&& get_number_immediate(bit_idx) == 0
|
||||||
&& (ivl_expr_width(sube) >= bit_wid)) {
|
&& (ivl_expr_width(sube) >= bit_wid)) {
|
||||||
|
|
||||||
|
|
@ -2307,6 +2383,12 @@ static struct vector_info draw_select_signal(ivl_expr_t sube,
|
||||||
res.wid = wid;
|
res.wid = wid;
|
||||||
assert(res.base);
|
assert(res.base);
|
||||||
|
|
||||||
|
lab_x = local_count++;
|
||||||
|
lab_end = local_count++;
|
||||||
|
|
||||||
|
/* If the index is 'bx then we just return 'bx. */
|
||||||
|
fprintf(vvp_out, " %%jmp/1 T_%d.%d, 4;\n", thread_count, lab_x);
|
||||||
|
|
||||||
use_wid = res.wid;
|
use_wid = res.wid;
|
||||||
if (use_wid > bit_wid)
|
if (use_wid > bit_wid)
|
||||||
use_wid = bit_wid;
|
use_wid = bit_wid;
|
||||||
|
|
@ -2317,6 +2399,11 @@ static struct vector_info draw_select_signal(ivl_expr_t sube,
|
||||||
fprintf(vvp_out, " %%movi %u, 0, %u;\n",
|
fprintf(vvp_out, " %%movi %u, 0, %u;\n",
|
||||||
res.base + use_wid, res.wid - use_wid);
|
res.base + use_wid, res.wid - use_wid);
|
||||||
|
|
||||||
|
fprintf(vvp_out, " %%jmp T_%d.%d;\n", thread_count, lab_end);
|
||||||
|
fprintf(vvp_out, "T_%d.%d ;\n", thread_count, lab_x);
|
||||||
|
fprintf(vvp_out, " %%mov %u, 2, %u;\n", res.base, res.wid);
|
||||||
|
fprintf(vvp_out, "T_%d.%d ;\n", thread_count, lab_end);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2335,6 +2422,7 @@ static void draw_select_signal_dest(ivl_expr_t sube,
|
||||||
if ((ivl_signal_dimensions(sig) == 0)
|
if ((ivl_signal_dimensions(sig) == 0)
|
||||||
&& (ivl_expr_width(sube) >= dest.wid)
|
&& (ivl_expr_width(sube) >= dest.wid)
|
||||||
&& number_is_immediate(bit_idx, 32, 0)
|
&& number_is_immediate(bit_idx, 32, 0)
|
||||||
|
&& ! number_is_unknown(bit_idx)
|
||||||
&& get_number_immediate(bit_idx) == 0) {
|
&& get_number_immediate(bit_idx) == 0) {
|
||||||
unsigned use_word = 0;
|
unsigned use_word = 0;
|
||||||
fprintf(vvp_out, " %%load/v %u, v%p_%u, %u; Select %u out of %u bits\n",
|
fprintf(vvp_out, " %%load/v %u, v%p_%u, %u; Select %u out of %u bits\n",
|
||||||
|
|
@ -2365,6 +2453,8 @@ static struct vector_info draw_select_expr(ivl_expr_t exp, unsigned wid,
|
||||||
ivl_expr_t shift = ivl_expr_oper2(exp);
|
ivl_expr_t shift = ivl_expr_oper2(exp);
|
||||||
|
|
||||||
int alloc_exclusive = (stuff_ok_flag&STUFF_OK_RO)? 0 : 1;
|
int alloc_exclusive = (stuff_ok_flag&STUFF_OK_RO)? 0 : 1;
|
||||||
|
int cmp;
|
||||||
|
unsigned lab_l, lab_end;
|
||||||
|
|
||||||
res.wid = wid;
|
res.wid = wid;
|
||||||
|
|
||||||
|
|
@ -2408,7 +2498,12 @@ static struct vector_info draw_select_expr(ivl_expr_t exp, unsigned wid,
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(vvp_out, " %%ix/get 0, %u, %u;\n", shiv.base, shiv.wid);
|
if (ivl_expr_signed(shift)) {
|
||||||
|
fprintf(vvp_out, " %%ix/get/s 0, %u, %u;\n", shiv.base,
|
||||||
|
shiv.wid);
|
||||||
|
} else {
|
||||||
|
fprintf(vvp_out, " %%ix/get 0, %u, %u;\n", shiv.base, shiv.wid);
|
||||||
|
}
|
||||||
clr_vector(shiv);
|
clr_vector(shiv);
|
||||||
|
|
||||||
/* If the subv result is a magic constant, then make a copy in
|
/* If the subv result is a magic constant, then make a copy in
|
||||||
|
|
@ -2422,7 +2517,27 @@ static struct vector_info draw_select_expr(ivl_expr_t exp, unsigned wid,
|
||||||
subv = res;
|
subv = res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lab_l = local_count++;
|
||||||
|
lab_end = local_count++;
|
||||||
|
/* If we have an undefined index then just produce a 'bx result. */
|
||||||
|
fprintf(vvp_out, " %%jmp/1 T_%d.%d, 4;\n", thread_count, lab_l);
|
||||||
|
|
||||||
|
cmp = allocate_word();
|
||||||
|
assert(subv.wid >= wid);
|
||||||
|
/* Determine if we need to shift a 'bx into the top. */
|
||||||
|
fprintf(vvp_out, " %%ix/load %u, %u, 0;\n", cmp, subv.wid - wid);
|
||||||
|
fprintf(vvp_out, " %%cmp/ws %u, 0;\n", cmp);
|
||||||
|
clr_word(cmp);
|
||||||
|
fprintf(vvp_out, " %%jmp/1 T_%d.%d, 5;\n", thread_count, lab_l);
|
||||||
|
/* Clear the cmp bit if the two values are equal. */
|
||||||
|
fprintf(vvp_out, " %%mov 4, 0, 1;\n");
|
||||||
fprintf(vvp_out, " %%shiftr/i0 %u, %u;\n", subv.base, subv.wid);
|
fprintf(vvp_out, " %%shiftr/i0 %u, %u;\n", subv.base, subv.wid);
|
||||||
|
fprintf(vvp_out, " %%jmp T_%d.%d;\n", thread_count, lab_end);
|
||||||
|
fprintf(vvp_out, "T_%d.%d ;\n", thread_count, lab_l);
|
||||||
|
/* Multiply by -1. */
|
||||||
|
fprintf(vvp_out, " %%ix/mul 0, %u, %u;\n", 0xFFFFFFFF, 0xFFFFFFFF);
|
||||||
|
fprintf(vvp_out, " %%shiftl/i0 %u, %u;\n", subv.base, subv.wid);
|
||||||
|
fprintf(vvp_out, "T_%d.%d ;\n", thread_count, lab_end);
|
||||||
|
|
||||||
if (subv.wid > wid) {
|
if (subv.wid > wid) {
|
||||||
res.base = subv.base;
|
res.base = subv.base;
|
||||||
|
|
@ -2456,7 +2571,7 @@ static void draw_select_expr_dest(ivl_expr_t exp, struct vector_info dest,
|
||||||
|
|
||||||
/* If the shift expression is not present, then this is really
|
/* If the shift expression is not present, then this is really
|
||||||
a pad expression, and that can be handled pretty
|
a pad expression, and that can be handled pretty
|
||||||
easily. Evalutate the subexpression into the destination,
|
easily. Evaluate the subexpression into the destination,
|
||||||
then pad in place. */
|
then pad in place. */
|
||||||
if (shift == 0) {
|
if (shift == 0) {
|
||||||
struct vector_info subv;
|
struct vector_info subv;
|
||||||
|
|
@ -2843,8 +2958,9 @@ static void draw_eval_expr_dest(ivl_expr_t exp, struct vector_info dest,
|
||||||
tmp = draw_eval_expr_wid(exp, dest.wid, stuff_ok_flag);
|
tmp = draw_eval_expr_wid(exp, dest.wid, stuff_ok_flag);
|
||||||
assert(tmp.wid == dest.wid);
|
assert(tmp.wid == dest.wid);
|
||||||
|
|
||||||
fprintf(vvp_out, " %%mov %u, %u, %u;\n",
|
/* If the replication is 0 we can have a zero width, so skip it. */
|
||||||
dest.base, tmp.base, dest.wid);
|
if (dest.wid) fprintf(vvp_out, " %%mov %u, %u, %u;\n",
|
||||||
|
dest.base, tmp.base, dest.wid);
|
||||||
|
|
||||||
if (tmp.base >= 8)
|
if (tmp.base >= 8)
|
||||||
save_expression_lookaside(tmp.base, exp, tmp.wid);
|
save_expression_lookaside(tmp.base, exp, tmp.wid);
|
||||||
|
|
@ -2867,6 +2983,12 @@ struct vector_info draw_eval_expr_wid(ivl_expr_t exp, unsigned wid,
|
||||||
res.base = 0;
|
res.base = 0;
|
||||||
res.wid = 0;
|
res.wid = 0;
|
||||||
break;
|
break;
|
||||||
|
case IVL_EX_EVENT:
|
||||||
|
fprintf(stderr, "%s:%u: vvp-tgt error: A named event is not "
|
||||||
|
"handled in this context (expression).\n",
|
||||||
|
ivl_expr_file(exp), ivl_expr_lineno(exp));
|
||||||
|
exit(1);
|
||||||
|
break;
|
||||||
|
|
||||||
case IVL_EX_STRING:
|
case IVL_EX_STRING:
|
||||||
res = draw_string_expr(exp, wid);
|
res = draw_string_expr(exp, wid);
|
||||||
|
|
|
||||||
|
|
@ -22,9 +22,6 @@
|
||||||
*/
|
*/
|
||||||
# include "vvp_priv.h"
|
# include "vvp_priv.h"
|
||||||
# include <string.h>
|
# include <string.h>
|
||||||
#ifdef HAVE_MALLOC_H
|
|
||||||
# include <malloc.h>
|
|
||||||
#endif
|
|
||||||
# include <stdlib.h>
|
# include <stdlib.h>
|
||||||
# include <math.h>
|
# include <math.h>
|
||||||
# include <assert.h>
|
# include <assert.h>
|
||||||
|
|
@ -55,9 +52,6 @@ static int draw_binary_real(ivl_expr_t expr)
|
||||||
{
|
{
|
||||||
int l, r = -1;
|
int l, r = -1;
|
||||||
|
|
||||||
/* If the opcode is a vector only opcode then the sub expression
|
|
||||||
* must not be a real expression, so use vector evaluation and
|
|
||||||
* then convert that result to a real value. */
|
|
||||||
switch (ivl_expr_opcode(expr)) {
|
switch (ivl_expr_opcode(expr)) {
|
||||||
case 'E':
|
case 'E':
|
||||||
case 'N':
|
case 'N':
|
||||||
|
|
@ -70,22 +64,8 @@ static int draw_binary_real(ivl_expr_t expr)
|
||||||
case 'A':
|
case 'A':
|
||||||
case 'O':
|
case 'O':
|
||||||
case 'X':
|
case 'X':
|
||||||
{
|
/* These should be caught in draw_eval_real(). */
|
||||||
struct vector_info vi;
|
assert(0);
|
||||||
int res;
|
|
||||||
const char*sign_flag;
|
|
||||||
|
|
||||||
vi = draw_eval_expr(expr, STUFF_OK_XZ);
|
|
||||||
res = allocate_word();
|
|
||||||
sign_flag = ivl_expr_signed(expr)? "/s" : "";
|
|
||||||
fprintf(vvp_out, " %%ix/get%s %d, %u, %u;\n",
|
|
||||||
sign_flag, res, vi.base, vi.wid);
|
|
||||||
|
|
||||||
fprintf(vvp_out, " %%cvt/ri %d, %d;\n", res, res);
|
|
||||||
|
|
||||||
clr_vector(vi);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
l = draw_eval_real(ivl_expr_oper1(expr));
|
l = draw_eval_real(ivl_expr_oper1(expr));
|
||||||
|
|
@ -120,16 +100,20 @@ static int draw_binary_real(ivl_expr_t expr)
|
||||||
int lab_out = local_count++;
|
int lab_out = local_count++;
|
||||||
int lab_r = local_count++;
|
int lab_r = local_count++;
|
||||||
/* If r is NaN, the go out and accept l as result. */
|
/* If r is NaN, the go out and accept l as result. */
|
||||||
fprintf(vvp_out, " %%cmp/wr %d, %d; Is NaN?\n", r, r);
|
fprintf(vvp_out, " %%cmp/wr %d, %d; Is NaN?\n", r, r);
|
||||||
fprintf(vvp_out, " %%jmp/0xz T_%d.%d, 4;\n", thread_count, lab_out);
|
fprintf(vvp_out, " %%jmp/0xz T_%d.%d, 4;\n", thread_count,
|
||||||
|
lab_out);
|
||||||
/* If l is NaN, the go out and accept r as result. */
|
/* If l is NaN, the go out and accept r as result. */
|
||||||
fprintf(vvp_out, " %%cmp/wr %d, %d; Is NaN?\n", l, l);
|
fprintf(vvp_out, " %%cmp/wr %d, %d; Is NaN?\n", l, l);
|
||||||
fprintf(vvp_out, " %%jmp/0xz T_%d.%d, 4;\n", thread_count, lab_r);
|
fprintf(vvp_out, " %%jmp/0xz T_%d.%d, 4;\n", thread_count,
|
||||||
|
lab_r);
|
||||||
/* If l <= r then go out. */
|
/* If l <= r then go out. */
|
||||||
fprintf(vvp_out, " %%cmp/wr %d, %d;\n", r, l);
|
fprintf(vvp_out, " %%cmp/wr %d, %d;\n", r, l);
|
||||||
fprintf(vvp_out, " %%jmp/0xz T_%d.%d, 5;\n", thread_count, lab_out);
|
fprintf(vvp_out, " %%jmp/0xz T_%d.%d, 5;\n", thread_count,
|
||||||
|
lab_out);
|
||||||
/* At this point we know we want r as the result. */
|
/* At this point we know we want r as the result. */
|
||||||
fprintf(vvp_out, "T_%d.%d %%mov/wr %d, %d;\n", thread_count, lab_r, l, r);
|
fprintf(vvp_out, "T_%d.%d %%mov/wr %d, %d;\n", thread_count,
|
||||||
|
lab_r, l, r);
|
||||||
fprintf(vvp_out, "T_%d.%d ;\n", thread_count, lab_out);
|
fprintf(vvp_out, "T_%d.%d ;\n", thread_count, lab_out);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -138,16 +122,20 @@ static int draw_binary_real(ivl_expr_t expr)
|
||||||
int lab_out = local_count++;
|
int lab_out = local_count++;
|
||||||
int lab_r = local_count++;
|
int lab_r = local_count++;
|
||||||
/* If r is NaN, the go out and accept l as result. */
|
/* If r is NaN, the go out and accept l as result. */
|
||||||
fprintf(vvp_out, " %%cmp/wr %d, %d; Is NaN?\n", r, r);
|
fprintf(vvp_out, " %%cmp/wr %d, %d; Is NaN?\n", r, r);
|
||||||
fprintf(vvp_out, " %%jmp/0xz T_%d.%d, 4;\n", thread_count, lab_out);
|
fprintf(vvp_out, " %%jmp/0xz T_%d.%d, 4;\n", thread_count,
|
||||||
|
lab_out);
|
||||||
/* If l is NaN, the go out and accept r as result. */
|
/* If l is NaN, the go out and accept r as result. */
|
||||||
fprintf(vvp_out, " %%cmp/wr %d, %d; Is NaN?\n", l, l);
|
fprintf(vvp_out, " %%cmp/wr %d, %d; Is NaN?\n", l, l);
|
||||||
fprintf(vvp_out, " %%jmp/0xz T_%d.%d, 4;\n", thread_count, lab_r);
|
fprintf(vvp_out, " %%jmp/0xz T_%d.%d, 4;\n", thread_count,
|
||||||
|
lab_r);
|
||||||
/* if l >= r then go out. */
|
/* if l >= r then go out. */
|
||||||
fprintf(vvp_out, " %%cmp/wr %d, %d;\n", l, r);
|
fprintf(vvp_out, " %%cmp/wr %d, %d;\n", l, r);
|
||||||
fprintf(vvp_out, " %%jmp/0xz T_%d.%d, 5;\n", thread_count, lab_out);
|
fprintf(vvp_out, " %%jmp/0xz T_%d.%d, 5;\n", thread_count,
|
||||||
|
lab_out);
|
||||||
|
|
||||||
fprintf(vvp_out, "T_%d.%d %%mov/wr %d, %d;\n", thread_count, lab_r, l, r);
|
fprintf(vvp_out, "T_%d.%d %%mov/wr %d, %d;\n", thread_count,
|
||||||
|
lab_r, l, r);
|
||||||
fprintf(vvp_out, "T_%d.%d ;\n", thread_count, lab_out);
|
fprintf(vvp_out, "T_%d.%d ;\n", thread_count, lab_out);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -508,8 +496,10 @@ static int draw_unary_real(ivl_expr_t expr)
|
||||||
return sub;
|
return sub;
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(vvp_out, "; XXXX unary (%c) on sube in %d\n", ivl_expr_opcode(expr), sub);
|
fprintf(vvp_out, "; XXXX unary (%c) on sube in %d\n",
|
||||||
fprintf(stderr, "XXXX evaluate unary (%c) on sube in %d\n", ivl_expr_opcode(expr), sub);
|
ivl_expr_opcode(expr), sub);
|
||||||
|
fprintf(stderr, "XXXX evaluate unary (%c) on sube in %d\n",
|
||||||
|
ivl_expr_opcode(expr), sub);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -517,6 +507,27 @@ int draw_eval_real(ivl_expr_t expr)
|
||||||
{
|
{
|
||||||
int res = 0;
|
int res = 0;
|
||||||
|
|
||||||
|
/* If this expression/sub-expression is not real then we need
|
||||||
|
* to evaluate it as a bit value and then convert the bit based
|
||||||
|
* result to a real value. This is required to get integer
|
||||||
|
* division to work correctly. */
|
||||||
|
if (ivl_expr_value(expr) != IVL_VT_REAL) {
|
||||||
|
struct vector_info vi;
|
||||||
|
int res;
|
||||||
|
const char*sign_flag;
|
||||||
|
|
||||||
|
vi = draw_eval_expr(expr, STUFF_OK_XZ);
|
||||||
|
res = allocate_word();
|
||||||
|
sign_flag = ivl_expr_signed(expr)? "/s" : "";
|
||||||
|
fprintf(vvp_out, " %%ix/get%s %d, %u, %u;\n", sign_flag, res,
|
||||||
|
vi.base, vi.wid);
|
||||||
|
|
||||||
|
fprintf(vvp_out, " %%cvt/ri %d, %d;\n", res, res);
|
||||||
|
|
||||||
|
clr_vector(vi);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
switch (ivl_expr_type(expr)) {
|
switch (ivl_expr_type(expr)) {
|
||||||
|
|
||||||
case IVL_EX_BINARY:
|
case IVL_EX_BINARY:
|
||||||
|
|
|
||||||
|
|
@ -140,6 +140,7 @@ int target_design(ivl_design_t des)
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(vvp_out);
|
fclose(vvp_out);
|
||||||
|
EOC_cleanup_drivers();
|
||||||
|
|
||||||
return rc + vvp_errors;
|
return rc + vvp_errors;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef __vvp_priv_H
|
#ifndef __vvp_priv_H
|
||||||
#define __vvp_priv_H
|
#define __vvp_priv_H
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2008 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2001-2009 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -141,6 +141,7 @@ struct vvp_nexus_data {
|
||||||
* cache it.
|
* cache it.
|
||||||
*/
|
*/
|
||||||
extern const char* draw_net_input(ivl_nexus_t nex);
|
extern const char* draw_net_input(ivl_nexus_t nex);
|
||||||
|
void EOC_cleanup_drivers();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* See draw_net_input.c for details on draw_net_input_x. (It would be
|
* See draw_net_input.c for details on draw_net_input_x. (It would be
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,8 @@ static void set_to_lvariable(ivl_lval_t lval,
|
||||||
|
|
||||||
if (part_off_ex == 0) {
|
if (part_off_ex == 0) {
|
||||||
part_off = 0;
|
part_off = 0;
|
||||||
} else if (number_is_immediate(part_off_ex, IMM_WID, 0)) {
|
} else if (number_is_immediate(part_off_ex, IMM_WID, 0) &&
|
||||||
|
!number_is_unknown(part_off_ex)) {
|
||||||
part_off = get_number_immediate(part_off_ex);
|
part_off = get_number_immediate(part_off_ex);
|
||||||
part_off_ex = 0;
|
part_off_ex = 0;
|
||||||
}
|
}
|
||||||
|
|
@ -96,6 +97,7 @@ static void set_to_lvariable(ivl_lval_t lval,
|
||||||
it to select the word, and pay no further heed to the
|
it to select the word, and pay no further heed to the
|
||||||
expression itself. */
|
expression itself. */
|
||||||
if (word_ix && number_is_immediate(word_ix, IMM_WID, 0)) {
|
if (word_ix && number_is_immediate(word_ix, IMM_WID, 0)) {
|
||||||
|
assert(! number_is_unknown(word_ix));
|
||||||
use_word = get_number_immediate(word_ix);
|
use_word = get_number_immediate(word_ix);
|
||||||
word_ix = 0;
|
word_ix = 0;
|
||||||
}
|
}
|
||||||
|
|
@ -233,12 +235,14 @@ static void assign_to_array_word(ivl_signal_t lsig, ivl_expr_t word_ix,
|
||||||
if (part_off_ex == 0) {
|
if (part_off_ex == 0) {
|
||||||
part_off = 0;
|
part_off = 0;
|
||||||
} else if (number_is_immediate(part_off_ex, IMM_WID, 0)) {
|
} else if (number_is_immediate(part_off_ex, IMM_WID, 0)) {
|
||||||
|
assert(! number_is_unknown(part_off_ex));
|
||||||
part_off = get_number_immediate(part_off_ex);
|
part_off = get_number_immediate(part_off_ex);
|
||||||
part_off_ex = 0;
|
part_off_ex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This code is common to all the different types of array delays. */
|
/* This code is common to all the different types of array delays. */
|
||||||
if (number_is_immediate(word_ix, IMM_WID, 0)) {
|
if (number_is_immediate(word_ix, IMM_WID, 0)) {
|
||||||
|
assert(! number_is_unknown(word_ix));
|
||||||
fprintf(vvp_out, " %%ix/load 3, %lu, 0; address\n",
|
fprintf(vvp_out, " %%ix/load 3, %lu, 0; address\n",
|
||||||
get_number_immediate(word_ix));
|
get_number_immediate(word_ix));
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -317,6 +321,7 @@ static void assign_to_lvector(ivl_lval_t lval, unsigned bit,
|
||||||
if (part_off_ex == 0) {
|
if (part_off_ex == 0) {
|
||||||
part_off = 0;
|
part_off = 0;
|
||||||
} else if (number_is_immediate(part_off_ex, IMM_WID, 0)) {
|
} else if (number_is_immediate(part_off_ex, IMM_WID, 0)) {
|
||||||
|
assert(! number_is_unknown(part_off_ex));
|
||||||
part_off = get_number_immediate(part_off_ex);
|
part_off = get_number_immediate(part_off_ex);
|
||||||
part_off_ex = 0;
|
part_off_ex = 0;
|
||||||
}
|
}
|
||||||
|
|
@ -647,7 +652,15 @@ static int show_stmt_assign_nb_real(ivl_statement_t net)
|
||||||
word_ix = ivl_lval_idx(lval);
|
word_ix = ivl_lval_idx(lval);
|
||||||
assert(word_ix);
|
assert(word_ix);
|
||||||
assert(number_is_immediate(word_ix, IMM_WID, 0));
|
assert(number_is_immediate(word_ix, IMM_WID, 0));
|
||||||
|
assert(! number_is_unknown(word_ix));
|
||||||
use_word = get_number_immediate(word_ix);
|
use_word = get_number_immediate(word_ix);
|
||||||
|
/* This method no longer works since variable arrays do not
|
||||||
|
* support <variable_id>_<idx> access any more. We need real
|
||||||
|
* array specific opcodes (%assign/ar, etc.). */
|
||||||
|
fprintf(stderr, "%s:%u: vvp-tgt sorry: non-blocking assignment "
|
||||||
|
"to a real array word is not supported.\n",
|
||||||
|
ivl_expr_file(rval), ivl_expr_lineno(rval));
|
||||||
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (del && (ivl_expr_type(del) == IVL_EX_DELAY)) {
|
if (del && (ivl_expr_type(del) == IVL_EX_DELAY)) {
|
||||||
|
|
@ -1105,11 +1118,13 @@ static void force_vector_to_lval(ivl_statement_t net, struct vector_info rvec)
|
||||||
part_off = 0;
|
part_off = 0;
|
||||||
} else {
|
} else {
|
||||||
assert(number_is_immediate(part_off_ex, IMM_WID, 0));
|
assert(number_is_immediate(part_off_ex, IMM_WID, 0));
|
||||||
|
assert(! number_is_unknown(part_off_ex));
|
||||||
part_off = get_number_immediate(part_off_ex);
|
part_off = get_number_immediate(part_off_ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (word_idx != 0) {
|
if (word_idx != 0) {
|
||||||
assert(number_is_immediate(word_idx, IMM_WID, 0));
|
assert(number_is_immediate(word_idx, IMM_WID, 0));
|
||||||
|
assert(! number_is_unknown(word_idx));
|
||||||
use_word = get_number_immediate(word_idx);
|
use_word = get_number_immediate(word_idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1174,6 +1189,7 @@ static void force_link_rval(ivl_statement_t net, ivl_expr_t rval)
|
||||||
* part select (this could give us multiple drivers). */
|
* part select (this could give us multiple drivers). */
|
||||||
part_off_ex = ivl_lval_part_off(lval);
|
part_off_ex = ivl_lval_part_off(lval);
|
||||||
if (ivl_signal_width(lsig) > ivl_signal_width(rsig) ||
|
if (ivl_signal_width(lsig) > ivl_signal_width(rsig) ||
|
||||||
|
// Do we need checks for number_is{immediate,unknown} of part_of_ex?
|
||||||
(part_off_ex && get_number_immediate(part_off_ex) != 0)) {
|
(part_off_ex && get_number_immediate(part_off_ex) != 0)) {
|
||||||
fprintf(stderr, "%s:%u: vvp-tgt sorry: cannot %s signal to "
|
fprintf(stderr, "%s:%u: vvp-tgt sorry: cannot %s signal to "
|
||||||
"a bit/part select.\n", ivl_expr_file(rval),
|
"a bit/part select.\n", ivl_expr_file(rval),
|
||||||
|
|
@ -1184,11 +1200,13 @@ static void force_link_rval(ivl_statement_t net, ivl_expr_t rval)
|
||||||
/* At least for now, only handle force to fixed words of an array. */
|
/* At least for now, only handle force to fixed words of an array. */
|
||||||
if ((lword_idx = ivl_lval_idx(lval)) != 0) {
|
if ((lword_idx = ivl_lval_idx(lval)) != 0) {
|
||||||
assert(number_is_immediate(lword_idx, IMM_WID, 0));
|
assert(number_is_immediate(lword_idx, IMM_WID, 0));
|
||||||
|
assert(! number_is_unknown(lword_idx));
|
||||||
use_lword = get_number_immediate(lword_idx);
|
use_lword = get_number_immediate(lword_idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((rword_idx = ivl_expr_oper1(rval)) != 0) {
|
if ((rword_idx = ivl_expr_oper1(rval)) != 0) {
|
||||||
assert(number_is_immediate(rword_idx, IMM_WID, 0));
|
assert(number_is_immediate(rword_idx, IMM_WID, 0));
|
||||||
|
assert(! number_is_unknown(rword_idx));
|
||||||
use_rword = get_number_immediate(rword_idx);
|
use_rword = get_number_immediate(rword_idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1272,11 +1290,13 @@ static int show_stmt_deassign(ivl_statement_t net)
|
||||||
part_off = 0;
|
part_off = 0;
|
||||||
if (part_off_ex != 0) {
|
if (part_off_ex != 0) {
|
||||||
assert(number_is_immediate(part_off_ex, 64, 0));
|
assert(number_is_immediate(part_off_ex, 64, 0));
|
||||||
|
assert(! number_is_unknown(part_off_ex));
|
||||||
part_off = get_number_immediate(part_off_ex);
|
part_off = get_number_immediate(part_off_ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (word_idx != 0) {
|
if (word_idx != 0) {
|
||||||
assert(number_is_immediate(word_idx, IMM_WID, 0));
|
assert(number_is_immediate(word_idx, IMM_WID, 0));
|
||||||
|
assert(! number_is_unknown(word_idx));
|
||||||
use_word = get_number_immediate(word_idx);
|
use_word = get_number_immediate(word_idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1567,6 +1587,7 @@ static int show_stmt_release(ivl_statement_t net)
|
||||||
part_off = 0;
|
part_off = 0;
|
||||||
if (part_off_ex != 0) {
|
if (part_off_ex != 0) {
|
||||||
assert(number_is_immediate(part_off_ex, 64, 0));
|
assert(number_is_immediate(part_off_ex, 64, 0));
|
||||||
|
assert(! number_is_unknown(part_off_ex));
|
||||||
part_off = get_number_immediate(part_off_ex);
|
part_off = get_number_immediate(part_off_ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1581,6 +1602,7 @@ static int show_stmt_release(ivl_statement_t net)
|
||||||
|
|
||||||
if (word_idx != 0) {
|
if (word_idx != 0) {
|
||||||
assert(number_is_immediate(word_idx, IMM_WID, 0));
|
assert(number_is_immediate(word_idx, IMM_WID, 0));
|
||||||
|
assert(! number_is_unknown(word_idx));
|
||||||
use_word = get_number_immediate(word_idx);
|
use_word = get_number_immediate(word_idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -558,6 +558,9 @@ static void draw_delay(ivl_net_logic_t lptr)
|
||||||
assert(number_is_immediate(d0, 64, 0));
|
assert(number_is_immediate(d0, 64, 0));
|
||||||
assert(number_is_immediate(d1, 64, 0));
|
assert(number_is_immediate(d1, 64, 0));
|
||||||
assert(number_is_immediate(d2, 64, 0));
|
assert(number_is_immediate(d2, 64, 0));
|
||||||
|
assert(! number_is_unknown(d0));
|
||||||
|
assert(! number_is_unknown(d1));
|
||||||
|
assert(! number_is_unknown(d2));
|
||||||
|
|
||||||
if (d0 == d1 && d1 == d2)
|
if (d0 == d1 && d1 == d2)
|
||||||
fprintf(vvp_out, " (%lu)", get_number_immediate(d0));
|
fprintf(vvp_out, " (%lu)", get_number_immediate(d0));
|
||||||
|
|
@ -615,6 +618,8 @@ static void draw_udp_in_scope(ivl_net_logic_t lptr)
|
||||||
static ivl_udp_t *udps = 0x0;
|
static ivl_udp_t *udps = 0x0;
|
||||||
static int nudps = 0;
|
static int nudps = 0;
|
||||||
int i;
|
int i;
|
||||||
|
unsigned ninp;
|
||||||
|
const char **input_strings;
|
||||||
|
|
||||||
for (i=0; i<nudps; i++)
|
for (i=0; i<nudps; i++)
|
||||||
if (udps[i] == udp)
|
if (udps[i] == udp)
|
||||||
|
|
@ -628,26 +633,38 @@ static void draw_udp_in_scope(ivl_net_logic_t lptr)
|
||||||
draw_udp_def(udp);
|
draw_udp_def(udp);
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(vvp_out, "L_%p .udp", lptr);
|
/*
|
||||||
fprintf(vvp_out, " UDP_%s",
|
* We need to process the arguments first so any evaluation code
|
||||||
vvp_mangle_id(ivl_udp_name(udp)));
|
* (.resolv, etc.) can be built before we build the .udp call.
|
||||||
draw_delay(lptr);
|
* This matches what is done for the other primitives.
|
||||||
|
*/
|
||||||
for (pdx = 1 ; pdx < ivl_logic_pins(lptr) ; pdx += 1) {
|
ninp = ivl_logic_pins(lptr) - 1;
|
||||||
ivl_nexus_t nex = ivl_logic_pin(lptr, pdx);
|
input_strings = calloc(ninp, sizeof(char*));
|
||||||
|
for (pdx = 0 ; pdx < ninp ; pdx += 1) {
|
||||||
|
ivl_nexus_t nex = ivl_logic_pin(lptr, pdx+1);
|
||||||
|
|
||||||
/* Unlike other logic gates, primitives may have unconnected
|
/* Unlike other logic gates, primitives may have unconnected
|
||||||
inputs. The proper behavior is to attach a HiZ to the
|
inputs. The proper behavior is to attach a HiZ to the
|
||||||
port. */
|
port. */
|
||||||
if (nex == 0) {
|
if (nex == 0) {
|
||||||
assert(ivl_logic_width(lptr) == 1);
|
assert(ivl_logic_width(lptr) == 1);
|
||||||
fprintf(vvp_out, ", C4<z>");
|
input_strings[pdx] = "C4<z>";
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
fprintf(vvp_out, ", %s", draw_net_input(nex));
|
input_strings[pdx] = draw_net_input(nex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fprintf(vvp_out, "L_%p .udp", lptr);
|
||||||
|
fprintf(vvp_out, " UDP_%s",
|
||||||
|
vvp_mangle_id(ivl_udp_name(udp)));
|
||||||
|
draw_delay(lptr);
|
||||||
|
|
||||||
|
for (pdx = 0 ; pdx < ninp ; pdx += 1) {
|
||||||
|
fprintf(vvp_out, ", %s", input_strings[pdx]);
|
||||||
|
}
|
||||||
|
free(input_strings);
|
||||||
|
|
||||||
fprintf(vvp_out, ";\n");
|
fprintf(vvp_out, ";\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -665,25 +682,12 @@ static void draw_logic_in_scope(ivl_net_logic_t lptr)
|
||||||
ivl_drive_t str0, str1;
|
ivl_drive_t str0, str1;
|
||||||
|
|
||||||
int level;
|
int level;
|
||||||
int ninp = ivl_logic_pins(lptr) - 1;
|
int ninp;
|
||||||
typedef const char*const_charp;
|
const char **input_strings;
|
||||||
const_charp*input_strings = calloc(ninp, sizeof(const_charp));
|
|
||||||
|
|
||||||
for (pdx = 0 ; pdx < ninp ; pdx += 1) {
|
|
||||||
ivl_nexus_t nex = ivl_logic_pin(lptr, pdx+1);
|
|
||||||
if (nex == 0) {
|
|
||||||
/* Only UDPs can have unconnected inputs. */
|
|
||||||
assert(ivl_logic_type(lptr) == IVL_LO_UDP);
|
|
||||||
input_strings[pdx] = 0;
|
|
||||||
} else {
|
|
||||||
input_strings[pdx] = draw_net_input(nex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (ivl_logic_type(lptr)) {
|
switch (ivl_logic_type(lptr)) {
|
||||||
|
|
||||||
case IVL_LO_UDP:
|
case IVL_LO_UDP:
|
||||||
free(input_strings);
|
|
||||||
draw_udp_in_scope(lptr);
|
draw_udp_in_scope(lptr);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -706,7 +710,6 @@ static void draw_logic_in_scope(ivl_net_logic_t lptr)
|
||||||
/* Skip pullup and pulldown objects. Things that have
|
/* Skip pullup and pulldown objects. Things that have
|
||||||
pull objects as inputs will instead generate the
|
pull objects as inputs will instead generate the
|
||||||
appropriate C<?> symbol. */
|
appropriate C<?> symbol. */
|
||||||
free(input_strings);
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case IVL_LO_AND:
|
case IVL_LO_AND:
|
||||||
|
|
@ -819,7 +822,6 @@ static void draw_logic_in_scope(ivl_net_logic_t lptr)
|
||||||
input_strings[pdx] = draw_net_input(ivl_logic_pin(lptr, pdx+1));
|
input_strings[pdx] = draw_net_input(ivl_logic_pin(lptr, pdx+1));
|
||||||
|
|
||||||
level = 0;
|
level = 0;
|
||||||
ninp = ivl_logic_pins(lptr) - 1;
|
|
||||||
while (ninp) {
|
while (ninp) {
|
||||||
int inst;
|
int inst;
|
||||||
for (inst = 0; inst < ninp; inst += 4) {
|
for (inst = 0; inst < ninp; inst += 4) {
|
||||||
|
|
@ -875,12 +877,18 @@ static void draw_logic_in_scope(ivl_net_logic_t lptr)
|
||||||
&& number_is_immediate(fall_exp,64,0)
|
&& number_is_immediate(fall_exp,64,0)
|
||||||
&& number_is_immediate(decay_exp,64,0)) {
|
&& number_is_immediate(decay_exp,64,0)) {
|
||||||
|
|
||||||
|
assert(! number_is_unknown(rise_exp));
|
||||||
|
assert(! number_is_unknown(fall_exp));
|
||||||
|
assert(! number_is_unknown(decay_exp));
|
||||||
fprintf(vvp_out, "L_%p .delay (%lu,%lu,%lu) L_%p/d;\n",
|
fprintf(vvp_out, "L_%p .delay (%lu,%lu,%lu) L_%p/d;\n",
|
||||||
lptr, get_number_immediate(rise_exp),
|
lptr, get_number_immediate(rise_exp),
|
||||||
get_number_immediate(rise_exp),
|
get_number_immediate(fall_exp),
|
||||||
get_number_immediate(rise_exp), lptr);
|
get_number_immediate(decay_exp), lptr);
|
||||||
} else {
|
} else {
|
||||||
ivl_signal_t sig;
|
ivl_signal_t sig;
|
||||||
|
// We do not currently support calculating the decay from
|
||||||
|
// the rise and fall variable delays.
|
||||||
|
assert(decay_exp != 0);
|
||||||
assert(ivl_expr_type(rise_exp) == IVL_EX_SIGNAL);
|
assert(ivl_expr_type(rise_exp) == IVL_EX_SIGNAL);
|
||||||
assert(ivl_expr_type(fall_exp) == IVL_EX_SIGNAL);
|
assert(ivl_expr_type(fall_exp) == IVL_EX_SIGNAL);
|
||||||
assert(ivl_expr_type(decay_exp) == IVL_EX_SIGNAL);
|
assert(ivl_expr_type(decay_exp) == IVL_EX_SIGNAL);
|
||||||
|
|
@ -1077,11 +1085,14 @@ static const char* draw_lpm_output_delay(ivl_lpm_t net)
|
||||||
assert(number_is_immediate(d_rise, 64, 0));
|
assert(number_is_immediate(d_rise, 64, 0));
|
||||||
assert(number_is_immediate(d_fall, 64, 0));
|
assert(number_is_immediate(d_fall, 64, 0));
|
||||||
assert(number_is_immediate(d_decay, 64, 0));
|
assert(number_is_immediate(d_decay, 64, 0));
|
||||||
|
assert(! number_is_unknown(d_rise));
|
||||||
|
assert(! number_is_unknown(d_fall));
|
||||||
|
assert(! number_is_unknown(d_decay));
|
||||||
dly = "/d";
|
dly = "/d";
|
||||||
fprintf(vvp_out, "L_%p .delay (%lu,%lu,%lu) L_%p/d;\n",
|
fprintf(vvp_out, "L_%p .delay (%lu,%lu,%lu) L_%p/d;\n",
|
||||||
net, get_number_immediate(d_rise),
|
net, get_number_immediate(d_rise),
|
||||||
get_number_immediate(d_rise),
|
get_number_immediate(d_fall),
|
||||||
get_number_immediate(d_rise), net);
|
get_number_immediate(d_decay), net);
|
||||||
}
|
}
|
||||||
|
|
||||||
return dly;
|
return dly;
|
||||||
|
|
@ -1333,7 +1344,7 @@ static unsigned lpm_concat_inputs(ivl_lpm_t net, unsigned start,
|
||||||
static void draw_lpm_concat(ivl_lpm_t net)
|
static void draw_lpm_concat(ivl_lpm_t net)
|
||||||
{
|
{
|
||||||
const char*src_table[4];
|
const char*src_table[4];
|
||||||
unsigned icnt = ivl_lpm_selects(net);
|
unsigned icnt = ivl_lpm_size(net);
|
||||||
const char*dly = draw_lpm_output_delay(net);
|
const char*dly = draw_lpm_output_delay(net);
|
||||||
|
|
||||||
if (icnt <= 4) {
|
if (icnt <= 4) {
|
||||||
|
|
@ -1859,12 +1870,14 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent)
|
||||||
fprintf(vvp_out, ">;\n");
|
fprintf(vvp_out, ">;\n");
|
||||||
break;
|
break;
|
||||||
case IVL_EX_REALNUM:
|
case IVL_EX_REALNUM:
|
||||||
fprintf(vvp_out, "P_%p .param/real \"%s\" %d %d, %s; value=%#g\n",
|
{ char *res = draw_Cr_to_string(ivl_expr_dvalue(pex));
|
||||||
par, ivl_parameter_basename(par),
|
fprintf(vvp_out, "P_%p .param/real \"%s\" %d %d, %s; "
|
||||||
ivl_file_table_index(ivl_parameter_file(par)),
|
"value=%#g\n", par, ivl_parameter_basename(par),
|
||||||
ivl_parameter_lineno(par),
|
ivl_file_table_index(ivl_parameter_file(par)),
|
||||||
draw_Cr_to_string(ivl_expr_dvalue(pex)),
|
ivl_parameter_lineno(par), res,
|
||||||
ivl_expr_dvalue(pex));
|
ivl_expr_dvalue(pex));
|
||||||
|
free(res);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(vvp_out, "; parameter type %d unsupported\n",
|
fprintf(vvp_out, "; parameter type %d unsupported\n",
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ License.
|
||||||
Verilog-A math library built for Icarus Verilog
|
Verilog-A math library built for Icarus Verilog
|
||||||
http://www.icarus.com/eda/verilog/
|
http://www.icarus.com/eda/verilog/
|
||||||
|
|
||||||
Copyright (C) 2007-2008 Cary R. (cygcary@yahoo.com)
|
Copyright (C) 2007-2009 Cary R. (cygcary@yahoo.com)
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|
@ -38,7 +38,7 @@ like all Verilog-D system functions the name must be prefixed with a '$'.
|
||||||
For reference the functions are:
|
For reference the functions are:
|
||||||
|
|
||||||
$ln(x) -- Natural logarithm
|
$ln(x) -- Natural logarithm
|
||||||
$log(x) -- Decimal logarithm
|
$log10(x) -- Decimal logarithm // $log is being deprecated!
|
||||||
$exp(x) -- Exponential
|
$exp(x) -- Exponential
|
||||||
$sqrt(x) -- Square root
|
$sqrt(x) -- Square root
|
||||||
$min(x,y) -- Minimum
|
$min(x,y) -- Minimum
|
||||||
|
|
|
||||||
|
|
@ -10,11 +10,11 @@
|
||||||
#
|
#
|
||||||
Summary: Icarus Verilog
|
Summary: Icarus Verilog
|
||||||
Name: verilog%{suff}
|
Name: verilog%{suff}
|
||||||
Version: 0.9.0.%{rev_date}
|
Version: 0.9.1
|
||||||
Release: 0
|
Release: 0
|
||||||
License: GPL
|
License: GPL
|
||||||
Group: Productivity/Scientific/Electronics
|
Group: Productivity/Scientific/Electronics
|
||||||
Source: verilog%{suff}-%{rev_date}.tar.gz
|
Source: verilog%{suff}-%{version}.tar.gz
|
||||||
URL: http://www.icarus.com/eda/verilog/index.html
|
URL: http://www.icarus.com/eda/verilog/index.html
|
||||||
Packager: Stephen Williams <steve@icarus.com>
|
Packager: Stephen Williams <steve@icarus.com>
|
||||||
|
|
||||||
|
|
@ -32,7 +32,7 @@ engineering formats, including simulation. It strives to be true
|
||||||
to the IEEE-1364 standard.
|
to the IEEE-1364 standard.
|
||||||
|
|
||||||
%prep
|
%prep
|
||||||
%setup -n verilog%{suff}-%{rev_date}
|
%setup -n verilog%{suff}-%{version}
|
||||||
|
|
||||||
%build
|
%build
|
||||||
if test X%{suff} != X
|
if test X%{suff} != X
|
||||||
|
|
|
||||||
41
verinum.cc
41
verinum.cc
|
|
@ -419,6 +419,7 @@ uint64_t verinum::as_ulong64() const
|
||||||
*/
|
*/
|
||||||
signed long verinum::as_long() const
|
signed long verinum::as_long() const
|
||||||
{
|
{
|
||||||
|
#define IVLLBITS (8 * sizeof(long) - 1)
|
||||||
if (nbits_ == 0)
|
if (nbits_ == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
@ -426,33 +427,43 @@ signed long verinum::as_long() const
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
signed long val = 0;
|
signed long val = 0;
|
||||||
|
unsigned diag_top = 0;
|
||||||
|
|
||||||
|
unsigned top = nbits_;
|
||||||
|
if (top > IVLLBITS) {
|
||||||
|
diag_top = top;
|
||||||
|
top = IVLLBITS;
|
||||||
|
}
|
||||||
|
int lost_bits=0;
|
||||||
|
|
||||||
if (has_sign_ && (bits_[nbits_-1] == V1)) {
|
if (has_sign_ && (bits_[nbits_-1] == V1)) {
|
||||||
unsigned top = nbits_;
|
|
||||||
if (top > (8 * sizeof(long) - 1))
|
|
||||||
top = 8 * sizeof(long) - 1;
|
|
||||||
|
|
||||||
val = -1;
|
val = -1;
|
||||||
signed long mask = ~1L;
|
signed long mask = ~1L;
|
||||||
for (unsigned idx = 0 ; idx < top ; idx += 1) {
|
for (unsigned idx = 0 ; idx < top ; idx += 1) {
|
||||||
if (bits_[idx] == V0)
|
if (bits_[idx] == V0) val &= mask;
|
||||||
val &= mask;
|
|
||||||
|
|
||||||
mask = (mask << 1) | 1L;
|
mask = (mask << 1) | 1L;
|
||||||
}
|
}
|
||||||
|
if (diag_top) {
|
||||||
|
for (unsigned idx = top; idx < diag_top; idx += 1) {
|
||||||
|
if (bits_[idx] == V0) lost_bits=1;
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
unsigned top = nbits_;
|
|
||||||
if (top > (8 * sizeof(long) - 1))
|
|
||||||
top = 8 * sizeof(long) - 1;
|
|
||||||
|
|
||||||
signed long mask = 1;
|
signed long mask = 1;
|
||||||
for (unsigned idx = 0 ; idx < top ; idx += 1, mask <<= 1)
|
for (unsigned idx = 0 ; idx < top ; idx += 1, mask <<= 1) {
|
||||||
if (bits_[idx] == V1)
|
if (bits_[idx] == V1) val |= mask;
|
||||||
val |= mask;
|
}
|
||||||
|
if (diag_top) {
|
||||||
|
for (unsigned idx = top; idx < diag_top; idx += 1) {
|
||||||
|
if (bits_[idx] == V1) lost_bits=1;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (lost_bits) cerr << "warning: verinum::as_long() truncated " <<
|
||||||
|
diag_top << " bits to " << IVLLBITS << ", returns " << val << endl;
|
||||||
return val;
|
return val;
|
||||||
|
#undef IVLLBITS
|
||||||
}
|
}
|
||||||
|
|
||||||
double verinum::as_double() const
|
double verinum::as_double() const
|
||||||
|
|
|
||||||
|
|
@ -174,6 +174,6 @@ verireal operator- (const verireal&l)
|
||||||
|
|
||||||
ostream& operator<< (ostream&out, const verireal&v)
|
ostream& operator<< (ostream&out, const verireal&v)
|
||||||
{
|
{
|
||||||
out << v.value_;
|
out << showpoint << v.value_;
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,5 +3,5 @@
|
||||||
* Edit this definition in version_base.in to define the base version
|
* Edit this definition in version_base.in to define the base version
|
||||||
* number for the compiled result.
|
* number for the compiled result.
|
||||||
*/
|
*/
|
||||||
#define VERSION "0.9.devel"
|
#define VERSION "0.9.1"
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@
|
||||||
# include "sys_priv.h"
|
# include "sys_priv.h"
|
||||||
# include <assert.h>
|
# include <assert.h>
|
||||||
# include <string.h>
|
# include <string.h>
|
||||||
|
# include <errno.h>
|
||||||
# include <ctype.h>
|
# include <ctype.h>
|
||||||
# include <stdio.h>
|
# include <stdio.h>
|
||||||
# include <stdlib.h>
|
# include <stdlib.h>
|
||||||
|
|
@ -263,7 +264,7 @@ static unsigned int get_format_char(char **rtn, int ljust, int plus,
|
||||||
s_vpi_value value;
|
s_vpi_value value;
|
||||||
char *result, *fmtb;
|
char *result, *fmtb;
|
||||||
unsigned int size;
|
unsigned int size;
|
||||||
unsigned int ini_size = 256; /* The initial size of the buffer. */
|
unsigned int ini_size = 512; /* The initial size of the buffer. */
|
||||||
|
|
||||||
/* Make sure the width fits in the initial buffer. */
|
/* Make sure the width fits in the initial buffer. */
|
||||||
if (width+1 > ini_size) ini_size = width + 1;
|
if (width+1 > ini_size) ini_size = width + 1;
|
||||||
|
|
@ -328,7 +329,7 @@ static unsigned int get_format_char(char **rtn, int ljust, int plus,
|
||||||
|
|
||||||
if (ld_zero == 1) {
|
if (ld_zero == 1) {
|
||||||
/* Strip the leading zeros if a width is not given. */
|
/* Strip the leading zeros if a width is not given. */
|
||||||
if (width == -1) while (*cp == '0') cp++;
|
if (width == -1) while (*cp == '0' && *(cp+1) != '\0') cp++;
|
||||||
/* Pad with leading zeros. */
|
/* Pad with leading zeros. */
|
||||||
else if (ljust == 0 && (signed)swidth < width) {
|
else if (ljust == 0 && (signed)swidth < width) {
|
||||||
unsigned pad = (unsigned)width - swidth;
|
unsigned pad = (unsigned)width - swidth;
|
||||||
|
|
@ -337,7 +338,7 @@ static unsigned int get_format_char(char **rtn, int ljust, int plus,
|
||||||
strcpy(cp+pad, value.value.str);
|
strcpy(cp+pad, value.value.str);
|
||||||
free_flag = 1;
|
free_flag = 1;
|
||||||
/* For a left aligned value also strip the leading zeros. */
|
/* For a left aligned value also strip the leading zeros. */
|
||||||
} else if (ljust != 0) while (*cp == '0') cp++;
|
} else if (ljust != 0) while (*cp == '0' && *(cp+1) != '\0') cp++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If a width was not given, use a width of zero. */
|
/* If a width was not given, use a width of zero. */
|
||||||
|
|
@ -488,12 +489,15 @@ static unsigned int get_format_char(char **rtn, int ljust, int plus,
|
||||||
|
|
||||||
/* If the default buffer is too small make it big enough.
|
/* If the default buffer is too small make it big enough.
|
||||||
*
|
*
|
||||||
* This size may not always be correct, but if the default
|
* This should always give enough space. The maximum double
|
||||||
* size is big enough for any practical value then all we
|
* is approximately 1.8*10^308 this means we could need 310
|
||||||
* need to worry about is extra padding and this should work
|
* characters plus the precision. We'll use 320 to give some
|
||||||
* correctly for that case, but since this uses the standard
|
* extra buffer space. The initial buffers size should work
|
||||||
* sprintf() routine we don't know exactly what it will do. */
|
* for most cases, but to be safe we add the precision to
|
||||||
|
* the maximum size (think %6.300f when passed 1.2*10^308). */
|
||||||
size = width + 1;
|
size = width + 1;
|
||||||
|
if (size < 320) size = 320;
|
||||||
|
size += prec;
|
||||||
if (size > ini_size) result = realloc(result, size*sizeof(char));
|
if (size > ini_size) result = realloc(result, size*sizeof(char));
|
||||||
sprintf(result, fmtb+1, value.value.real);
|
sprintf(result, fmtb+1, value.value.real);
|
||||||
size = strlen(result) + 1;
|
size = strlen(result) + 1;
|
||||||
|
|
@ -583,7 +587,8 @@ static unsigned int get_format_char(char **rtn, int ljust, int plus,
|
||||||
type = vpi_get(vpiType, info->items[*idx]);
|
type = vpi_get(vpiType, info->items[*idx]);
|
||||||
if (((type == vpiConstant || type == vpiParameter) &&
|
if (((type == vpiConstant || type == vpiParameter) &&
|
||||||
vpi_get(vpiConstType, info->items[*idx]) == vpiRealConst) ||
|
vpi_get(vpiConstType, info->items[*idx]) == vpiRealConst) ||
|
||||||
type == vpiRealVar ) {
|
type == vpiRealVar || (type == vpiSysFuncCall &&
|
||||||
|
vpi_get(vpiFuncType, info->items[*idx]) == vpiRealFunc)) {
|
||||||
value.format = vpiRealVal;
|
value.format = vpiRealVal;
|
||||||
} else {
|
} else {
|
||||||
value.format = vpiDecStrVal;
|
value.format = vpiDecStrVal;
|
||||||
|
|
@ -1116,18 +1121,26 @@ static PLI_INT32 sys_display_calltf(PLI_BYTE8 *name)
|
||||||
|
|
||||||
/* Get the file/MC descriptor and verify it is valid. */
|
/* Get the file/MC descriptor and verify it is valid. */
|
||||||
if(name[1] == 'f') {
|
if(name[1] == 'f') {
|
||||||
|
errno = 0;
|
||||||
vpiHandle arg = vpi_scan(argv);
|
vpiHandle arg = vpi_scan(argv);
|
||||||
s_vpi_value val;
|
s_vpi_value val;
|
||||||
val.format = vpiIntVal;
|
val.format = vpiIntVal;
|
||||||
vpi_get_value(arg, &val);
|
vpi_get_value(arg, &val);
|
||||||
fd_mcd = val.value.integer;
|
fd_mcd = val.value.integer;
|
||||||
|
|
||||||
|
/* If the MCD is zero we have nothing to do so just return. */
|
||||||
|
if (fd_mcd == 0) {
|
||||||
|
vpi_free_object(argv);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if ((! IS_MCD(fd_mcd) && vpi_get_file(fd_mcd) == NULL) ||
|
if ((! IS_MCD(fd_mcd) && vpi_get_file(fd_mcd) == NULL) ||
|
||||||
( IS_MCD(fd_mcd) && my_mcd_printf(fd_mcd, "") == EOF)) {
|
( IS_MCD(fd_mcd) && my_mcd_printf(fd_mcd, "") == EOF)) {
|
||||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||||
(int)vpi_get(vpiLineNo, callh));
|
(int)vpi_get(vpiLineNo, callh));
|
||||||
vpi_printf("invalid file descriptor/MCD (0x%x) given "
|
vpi_printf("invalid file descriptor/MCD (0x%x) given "
|
||||||
"to %s.\n", fd_mcd, name);
|
"to %s.\n", fd_mcd, name);
|
||||||
vpi_control(vpiFinish, 1);
|
errno = EBADF;
|
||||||
vpi_free_object(argv);
|
vpi_free_object(argv);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -1176,23 +1189,29 @@ static PLI_INT32 sys_display_calltf(PLI_BYTE8 *name)
|
||||||
*/
|
*/
|
||||||
static PLI_INT32 strobe_cb(p_cb_data cb)
|
static PLI_INT32 strobe_cb(p_cb_data cb)
|
||||||
{
|
{
|
||||||
char* result;
|
char* result = NULL;
|
||||||
unsigned int size, location=0;
|
unsigned int size, location=0;
|
||||||
struct strobe_cb_info*info = (struct strobe_cb_info*)cb->user_data;
|
struct strobe_cb_info*info = (struct strobe_cb_info*)cb->user_data;
|
||||||
|
|
||||||
/* Because %u and %z may put embedded NULL characters into the
|
/* We really need to cancel any $fstrobe() calls for a file when it
|
||||||
* returned string strlen() may not match the real size! */
|
* is closed, but for now we will just skip processing the result.
|
||||||
result = get_display(&size, info);
|
* Which has the same basic effect. */
|
||||||
while (location < size) {
|
if ((! IS_MCD(info->fd_mcd) && vpi_get_file(info->fd_mcd) != NULL) ||
|
||||||
if (result[location] == '\0') {
|
( IS_MCD(info->fd_mcd) && my_mcd_printf(info->fd_mcd, "") != EOF)) {
|
||||||
my_mcd_printf(info->fd_mcd, "%c", '\0');
|
/* Because %u and %z may put embedded NULL characters into the
|
||||||
location += 1;
|
* returned string strlen() may not match the real size! */
|
||||||
} else {
|
result = get_display(&size, info);
|
||||||
my_mcd_printf(info->fd_mcd, "%s", &result[location]);
|
while (location < size) {
|
||||||
location += strlen(&result[location]);
|
if (result[location] == '\0') {
|
||||||
|
my_mcd_printf(info->fd_mcd, "%c", '\0');
|
||||||
|
location += 1;
|
||||||
|
} else {
|
||||||
|
my_mcd_printf(info->fd_mcd, "%s", &result[location]);
|
||||||
|
location += strlen(&result[location]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
my_mcd_printf(info->fd_mcd, "\n");
|
||||||
}
|
}
|
||||||
my_mcd_printf(info->fd_mcd, "\n");
|
|
||||||
|
|
||||||
free(info->filename);
|
free(info->filename);
|
||||||
free(info->items);
|
free(info->items);
|
||||||
|
|
@ -1222,18 +1241,26 @@ static PLI_INT32 sys_strobe_calltf(PLI_BYTE8*name)
|
||||||
|
|
||||||
/* Get the file/MC descriptor and verify it is valid. */
|
/* Get the file/MC descriptor and verify it is valid. */
|
||||||
if(name[1] == 'f') {
|
if(name[1] == 'f') {
|
||||||
|
errno = 0;
|
||||||
vpiHandle arg = vpi_scan(argv);
|
vpiHandle arg = vpi_scan(argv);
|
||||||
s_vpi_value val;
|
s_vpi_value val;
|
||||||
val.format = vpiIntVal;
|
val.format = vpiIntVal;
|
||||||
vpi_get_value(arg, &val);
|
vpi_get_value(arg, &val);
|
||||||
fd_mcd = val.value.integer;
|
fd_mcd = val.value.integer;
|
||||||
|
|
||||||
|
/* If the MCD is zero we have nothing to do so just return. */
|
||||||
|
if (fd_mcd == 0) {
|
||||||
|
vpi_free_object(argv);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if ((! IS_MCD(fd_mcd) && vpi_get_file(fd_mcd) == NULL) ||
|
if ((! IS_MCD(fd_mcd) && vpi_get_file(fd_mcd) == NULL) ||
|
||||||
( IS_MCD(fd_mcd) && my_mcd_printf(fd_mcd, "") == EOF)) {
|
( IS_MCD(fd_mcd) && my_mcd_printf(fd_mcd, "") == EOF)) {
|
||||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||||
(int)vpi_get(vpiLineNo, callh));
|
(int)vpi_get(vpiLineNo, callh));
|
||||||
vpi_printf("invalid file descriptor/MCD (0x%x) given "
|
vpi_printf("invalid file descriptor/MCD (0x%x) given "
|
||||||
"to %s.\n", fd_mcd, name);
|
"to %s.\n", fd_mcd, name);
|
||||||
vpi_control(vpiFinish, 1);
|
errno = EBADF;
|
||||||
vpi_free_object(argv);
|
vpi_free_object(argv);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
486
vpi/sys_fileio.c
486
vpi/sys_fileio.c
|
|
@ -21,13 +21,13 @@
|
||||||
# include "sys_priv.h"
|
# include "sys_priv.h"
|
||||||
# include <assert.h>
|
# include <assert.h>
|
||||||
# include <ctype.h>
|
# include <ctype.h>
|
||||||
|
# include <errno.h>
|
||||||
# include <string.h>
|
# include <string.h>
|
||||||
# include <stdio.h>
|
# include <stdio.h>
|
||||||
# include <stdlib.h>
|
# include <stdlib.h>
|
||||||
|
|
||||||
#define IS_MCD(mcd) !((mcd)>>31&1)
|
#define IS_MCD(mcd) !((mcd)>>31&1)
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Implement the $fopen system function.
|
* Implement the $fopen system function.
|
||||||
*/
|
*/
|
||||||
|
|
@ -83,6 +83,8 @@ static PLI_INT32 sys_fopen_calltf(PLI_BYTE8*name)
|
||||||
vpiHandle fileh = vpi_scan(argv);
|
vpiHandle fileh = vpi_scan(argv);
|
||||||
char *fname;
|
char *fname;
|
||||||
vpiHandle mode = vpi_scan(argv);
|
vpiHandle mode = vpi_scan(argv);
|
||||||
|
errno = 0;
|
||||||
|
|
||||||
/* Get the mode handle if it exists. */
|
/* Get the mode handle if it exists. */
|
||||||
if (mode) {
|
if (mode) {
|
||||||
char *esc_md;
|
char *esc_md;
|
||||||
|
|
@ -151,10 +153,13 @@ static PLI_INT32 sys_fopen_calltf(PLI_BYTE8*name)
|
||||||
}
|
}
|
||||||
|
|
||||||
fname = get_filename(callh, name, fileh);
|
fname = get_filename(callh, name, fileh);
|
||||||
if (fname == 0 && mode) free(mode_string);
|
|
||||||
|
|
||||||
/* If either the mode or file name are not valid just return. */
|
/* If either the mode or file name are not valid just return. */
|
||||||
if (fail || fname == 0) return 0;
|
if (fail || fname == 0) {
|
||||||
|
free(fname);
|
||||||
|
if (mode) free(mode_string);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
val.format = vpiIntVal;
|
val.format = vpiIntVal;
|
||||||
if (mode) {
|
if (mode) {
|
||||||
|
|
@ -164,6 +169,7 @@ static PLI_INT32 sys_fopen_calltf(PLI_BYTE8*name)
|
||||||
val.value.integer = vpi_mcd_open(fname);
|
val.value.integer = vpi_mcd_open(fname);
|
||||||
|
|
||||||
vpi_put_value(callh, &val, 0, vpiNoDelay);
|
vpi_put_value(callh, &val, 0, vpiNoDelay);
|
||||||
|
free(fname);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -179,7 +185,7 @@ static PLI_INT32 sys_fopenrwa_calltf(PLI_BYTE8*name)
|
||||||
vpiHandle argv = vpi_iterate(vpiArgument, callh);
|
vpiHandle argv = vpi_iterate(vpiArgument, callh);
|
||||||
s_vpi_value val;
|
s_vpi_value val;
|
||||||
char *mode, *fname;
|
char *mode, *fname;
|
||||||
|
errno = 0;
|
||||||
|
|
||||||
/* Get the mode. */
|
/* Get the mode. */
|
||||||
mode = name + strlen(name) - 1;
|
mode = name + strlen(name) - 1;
|
||||||
|
|
@ -208,7 +214,7 @@ static PLI_INT32 sys_fclose_calltf(PLI_BYTE8*name)
|
||||||
vpiHandle fd = vpi_scan(argv);
|
vpiHandle fd = vpi_scan(argv);
|
||||||
s_vpi_value val;
|
s_vpi_value val;
|
||||||
PLI_UINT32 fd_mcd;
|
PLI_UINT32 fd_mcd;
|
||||||
char *str = ""; /* This prevents the compiler from complaining. */
|
errno = 0;
|
||||||
|
|
||||||
vpi_free_object(argv);
|
vpi_free_object(argv);
|
||||||
|
|
||||||
|
|
@ -218,15 +224,19 @@ static PLI_INT32 sys_fclose_calltf(PLI_BYTE8*name)
|
||||||
fd_mcd = val.value.integer;
|
fd_mcd = val.value.integer;
|
||||||
|
|
||||||
if ((! IS_MCD(fd_mcd) && vpi_get_file(fd_mcd) == NULL) ||
|
if ((! IS_MCD(fd_mcd) && vpi_get_file(fd_mcd) == NULL) ||
|
||||||
( IS_MCD(fd_mcd) && vpi_mcd_printf(fd_mcd, str) == EOF)) {
|
( IS_MCD(fd_mcd) && vpi_mcd_printf(fd_mcd, "%s", "") == EOF) ||
|
||||||
|
(! fd_mcd)) {
|
||||||
vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh),
|
vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||||
(int)vpi_get(vpiLineNo, callh));
|
(int)vpi_get(vpiLineNo, callh));
|
||||||
vpi_printf("invalid file descriptor/MCD (0x%x) given to %s.\n",
|
vpi_printf("invalid file descriptor/MCD (0x%x) given to %s.\n",
|
||||||
fd_mcd, name);
|
fd_mcd, name);
|
||||||
|
errno = EBADF;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We need to cancel any active $fstrobe()'s for this FD/MCD. */
|
/* We need to cancel any active $fstrobe()'s for this FD/MCD.
|
||||||
|
* For now we check in the strobe callback and skip the output
|
||||||
|
* generation when needed. */
|
||||||
vpi_mcd_close(fd_mcd);
|
vpi_mcd_close(fd_mcd);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -243,7 +253,7 @@ static PLI_INT32 sys_fflush_calltf(PLI_BYTE8*name)
|
||||||
s_vpi_value val;
|
s_vpi_value val;
|
||||||
PLI_UINT32 fd_mcd;
|
PLI_UINT32 fd_mcd;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
char *str = ""; /* This prevents the compiler from complaining. */
|
errno = 0;
|
||||||
|
|
||||||
/* If we have no argument then flush all the streams. */
|
/* If we have no argument then flush all the streams. */
|
||||||
if (argv == 0) {
|
if (argv == 0) {
|
||||||
|
|
@ -258,12 +268,17 @@ static PLI_INT32 sys_fflush_calltf(PLI_BYTE8*name)
|
||||||
vpi_get_value(arg, &val);
|
vpi_get_value(arg, &val);
|
||||||
fd_mcd = val.value.integer;
|
fd_mcd = val.value.integer;
|
||||||
|
|
||||||
|
/* If the MCD is zero we have nothing to do so just return. */
|
||||||
|
if (fd_mcd == 0) return 0;
|
||||||
|
|
||||||
if ((! IS_MCD(fd_mcd) && vpi_get_file(fd_mcd) == NULL) ||
|
if ((! IS_MCD(fd_mcd) && vpi_get_file(fd_mcd) == NULL) ||
|
||||||
( IS_MCD(fd_mcd) && vpi_mcd_printf(fd_mcd, str) == EOF)) {
|
( IS_MCD(fd_mcd) && vpi_mcd_printf(fd_mcd, "%s", "") == EOF) ||
|
||||||
|
(! fd_mcd)) {
|
||||||
vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh),
|
vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||||
(int)vpi_get(vpiLineNo, callh));
|
(int)vpi_get(vpiLineNo, callh));
|
||||||
vpi_printf("invalid file descriptor/MCD (0x%x) given to %s.\n",
|
vpi_printf("invalid file descriptor/MCD (0x%x) given to %s.\n",
|
||||||
fd_mcd, name);
|
fd_mcd, name);
|
||||||
|
errno = EBADF;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -287,7 +302,7 @@ static PLI_INT32 sys_fputc_calltf(PLI_BYTE8*name)
|
||||||
PLI_UINT32 fd_mcd;
|
PLI_UINT32 fd_mcd;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
unsigned char chr;
|
unsigned char chr;
|
||||||
(void) name; /* Not used! */
|
errno = 0;
|
||||||
|
|
||||||
/* Get the character. */
|
/* Get the character. */
|
||||||
arg = vpi_scan(argv);
|
arg = vpi_scan(argv);
|
||||||
|
|
@ -311,9 +326,12 @@ static PLI_INT32 sys_fputc_calltf(PLI_BYTE8*name)
|
||||||
(int)vpi_get(vpiLineNo, callh));
|
(int)vpi_get(vpiLineNo, callh));
|
||||||
vpi_printf("invalid file descriptor (0x%x) given to %s.\n", fd_mcd,
|
vpi_printf("invalid file descriptor (0x%x) given to %s.\n", fd_mcd,
|
||||||
name);
|
name);
|
||||||
|
errno = EBADF;
|
||||||
val.value.integer = EOF;
|
val.value.integer = EOF;
|
||||||
} else
|
} else {
|
||||||
val.value.integer = fputc(chr, fp);
|
val.value.integer = fputc(chr, fp);
|
||||||
|
if (val.value.integer != EOF) val.value.integer = 0;
|
||||||
|
}
|
||||||
vpi_put_value(callh, &val, 0, vpiNoDelay);
|
vpi_put_value(callh, &val, 0, vpiNoDelay);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -377,7 +395,7 @@ static PLI_INT32 sys_fgets_calltf(PLI_BYTE8*name)
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
PLI_INT32 reg_size;
|
PLI_INT32 reg_size;
|
||||||
char*text;
|
char*text;
|
||||||
(void) name; /* Not used! */
|
errno = 0;
|
||||||
|
|
||||||
/* Get the register handle. */
|
/* Get the register handle. */
|
||||||
regh = vpi_scan(argv);
|
regh = vpi_scan(argv);
|
||||||
|
|
@ -396,6 +414,7 @@ static PLI_INT32 sys_fgets_calltf(PLI_BYTE8*name)
|
||||||
(int)vpi_get(vpiLineNo, callh));
|
(int)vpi_get(vpiLineNo, callh));
|
||||||
vpi_printf("invalid file descriptor (0x%x) given to %s.\n", fd_mcd,
|
vpi_printf("invalid file descriptor (0x%x) given to %s.\n", fd_mcd,
|
||||||
name);
|
name);
|
||||||
|
errno = EBADF;
|
||||||
val.format = vpiIntVal;
|
val.format = vpiIntVal;
|
||||||
val.value.integer = 0;
|
val.value.integer = 0;
|
||||||
vpi_put_value(callh, &val, 0, vpiNoDelay);
|
vpi_put_value(callh, &val, 0, vpiNoDelay);
|
||||||
|
|
@ -429,6 +448,263 @@ static PLI_INT32 sys_fgets_calltf(PLI_BYTE8*name)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PLI_INT32 sys_fread_compiletf(PLI_BYTE8*name)
|
||||||
|
{
|
||||||
|
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
|
||||||
|
vpiHandle argv = vpi_iterate(vpiArgument, callh);
|
||||||
|
vpiHandle arg;
|
||||||
|
PLI_INT32 type;
|
||||||
|
|
||||||
|
/* We must have at least two arguments. */
|
||||||
|
if (argv == 0) {
|
||||||
|
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||||
|
(int)vpi_get(vpiLineNo, callh));
|
||||||
|
vpi_printf("%s requires two arguments.\n", name);
|
||||||
|
vpi_control(vpiFinish, 1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check that the first required argument is a register or memory. */
|
||||||
|
type = vpi_get(vpiType, vpi_scan(argv));
|
||||||
|
if (type != vpiReg && type != vpiMemory) {
|
||||||
|
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||||
|
(int)vpi_get(vpiLineNo, callh));
|
||||||
|
vpi_printf("%s's first argument must be a reg or memory.\n", name);
|
||||||
|
vpi_control(vpiFinish, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check that the second required argument is numeric (a fd). */
|
||||||
|
arg = vpi_scan(argv);
|
||||||
|
if (! arg) {
|
||||||
|
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||||
|
(int)vpi_get(vpiLineNo, callh));
|
||||||
|
vpi_printf("%s requires a second (file descriptor) argument.\n",
|
||||||
|
name);
|
||||||
|
vpi_control(vpiFinish, 1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! is_numeric_obj(arg)) {
|
||||||
|
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||||
|
(int)vpi_get(vpiLineNo, callh));
|
||||||
|
vpi_printf("%s's second argument must be numeric.\n", name);
|
||||||
|
vpi_control(vpiFinish, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If given check that the third argument is numeric (start).
|
||||||
|
*
|
||||||
|
* Technically you can give the fourth argument (count) with
|
||||||
|
* out a third argument (start), but Icarus does not currently
|
||||||
|
* support missing function arguments!
|
||||||
|
*/
|
||||||
|
arg = vpi_scan(argv);
|
||||||
|
if (arg) {
|
||||||
|
if (! is_numeric_obj(arg)) {
|
||||||
|
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||||
|
(int)vpi_get(vpiLineNo, callh));
|
||||||
|
vpi_printf("%s's third argument must be numeric.\n", name);
|
||||||
|
vpi_control(vpiFinish, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If given check that the fourth argument is numeric (count). */
|
||||||
|
arg = vpi_scan(argv);
|
||||||
|
if (arg) {
|
||||||
|
if (! is_numeric_obj(arg)) {
|
||||||
|
vpi_printf("ERROR: %s:%d: ",
|
||||||
|
vpi_get_str(vpiFile, callh),
|
||||||
|
(int)vpi_get(vpiLineNo, callh));
|
||||||
|
vpi_printf("%s's fourth argument must be numeric.\n",
|
||||||
|
name);
|
||||||
|
vpi_control(vpiFinish, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure there are no extra arguments. */
|
||||||
|
check_for_extra_args(argv, callh, name, "four arguments", 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The pattern here is get the current vector, load the new bits on
|
||||||
|
* top of the old ones and then put the modified vector. We need the
|
||||||
|
* "get" first so that if we run out of bits in the file we keep the
|
||||||
|
* original ones.
|
||||||
|
*/
|
||||||
|
static unsigned fread_word(FILE *fp, vpiHandle word,
|
||||||
|
unsigned words, unsigned bpe, s_vpi_vecval *vector)
|
||||||
|
{
|
||||||
|
unsigned rtn, clr_mask, bnum;
|
||||||
|
int bidx, byte;
|
||||||
|
s_vpi_value val;
|
||||||
|
struct t_vpi_vecval *cur = &vector[words-1];
|
||||||
|
|
||||||
|
rtn = 0;
|
||||||
|
|
||||||
|
/* Get the current bits from the register and copy them to
|
||||||
|
* my local vector. */
|
||||||
|
val.format = vpiVectorVal;
|
||||||
|
vpi_get_value(word, &val);
|
||||||
|
for (bidx = 0; bidx < words; bidx += 1) {
|
||||||
|
vector[bidx].aval = val.value.vector[bidx].aval;
|
||||||
|
vector[bidx].bval = val.value.vector[bidx].bval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy the bytes to the local vector MSByte first. */
|
||||||
|
for (bidx = bpe-1; bidx >= 0; bidx -= 1) {
|
||||||
|
byte = fgetc(fp);
|
||||||
|
if (byte == EOF) break;
|
||||||
|
/* Clear the current byte and load the new value. */
|
||||||
|
bnum = bidx % 4;
|
||||||
|
clr_mask = ~(0xff << bnum*8);
|
||||||
|
cur->aval &= clr_mask;
|
||||||
|
cur->bval &= clr_mask;
|
||||||
|
cur->aval |= byte << bnum*8;
|
||||||
|
rtn += 1;
|
||||||
|
if (bnum == 0) cur -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Put the updated bits into the register. */
|
||||||
|
val.value.vector = vector;
|
||||||
|
vpi_put_value(word, &val, 0, vpiNoDelay);
|
||||||
|
|
||||||
|
return rtn;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PLI_INT32 sys_fread_calltf(PLI_BYTE8*name)
|
||||||
|
{
|
||||||
|
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
|
||||||
|
vpiHandle argv = vpi_iterate(vpiArgument, callh);
|
||||||
|
vpiHandle arg, mem_reg;
|
||||||
|
s_vpi_value val;
|
||||||
|
PLI_UINT32 fd_mcd;
|
||||||
|
PLI_INT32 start, count, width, rtn;
|
||||||
|
unsigned is_mem, idx, bpe, words;
|
||||||
|
FILE *fp;
|
||||||
|
s_vpi_vecval *vector;
|
||||||
|
errno = 0;
|
||||||
|
|
||||||
|
/* Get the register/memory. */
|
||||||
|
mem_reg = vpi_scan(argv);
|
||||||
|
|
||||||
|
/* Get the file descriptor. */
|
||||||
|
arg = vpi_scan(argv);
|
||||||
|
val.format = vpiIntVal;
|
||||||
|
vpi_get_value(arg, &val);
|
||||||
|
fd_mcd = val.value.integer;
|
||||||
|
|
||||||
|
/* Return 0 if this is not a valid fd. */
|
||||||
|
fp = vpi_get_file(fd_mcd);
|
||||||
|
if (!fp) {
|
||||||
|
vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||||
|
(int)vpi_get(vpiLineNo, callh));
|
||||||
|
vpi_printf("invalid file descriptor (0x%x) given to %s.\n", fd_mcd,
|
||||||
|
name);
|
||||||
|
errno = EBADF;
|
||||||
|
val.format = vpiIntVal;
|
||||||
|
val.value.integer = 0;
|
||||||
|
vpi_put_value(callh, &val, 0, vpiNoDelay);
|
||||||
|
vpi_free_object(argv);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Are we reading into a memory? */
|
||||||
|
if (vpi_get(vpiType, mem_reg) == vpiReg) is_mem = 0;
|
||||||
|
else is_mem = 1;
|
||||||
|
|
||||||
|
/* We only need to get these for memories. */
|
||||||
|
if (is_mem) {
|
||||||
|
PLI_INT32 left, right, max, min;
|
||||||
|
|
||||||
|
/* Get the left and right memory address. */
|
||||||
|
val.format = vpiIntVal;
|
||||||
|
vpi_get_value(vpi_handle(vpiLeftRange, mem_reg), &val);
|
||||||
|
left = val.value.integer;
|
||||||
|
val.format = vpiIntVal;
|
||||||
|
vpi_get_value(vpi_handle(vpiRightRange, mem_reg), &val);
|
||||||
|
right = val.value.integer;
|
||||||
|
max = (left > right) ? left : right;
|
||||||
|
min = (left < right) ? left : right;
|
||||||
|
|
||||||
|
/* Get the starting address (optional). */
|
||||||
|
arg = vpi_scan(argv);
|
||||||
|
if (arg) {
|
||||||
|
val.format = vpiIntVal;
|
||||||
|
vpi_get_value(arg, &val);
|
||||||
|
start = val.value.integer;
|
||||||
|
if (start < min || start > max) {
|
||||||
|
vpi_printf("WARNING: %s:%d: ",
|
||||||
|
vpi_get_str(vpiFile, callh),
|
||||||
|
(int)vpi_get(vpiLineNo, callh));
|
||||||
|
vpi_printf("%s's start argument (%d) is outside "
|
||||||
|
"memory range [%d:%d].\n", name, start,
|
||||||
|
left, right);
|
||||||
|
val.format = vpiIntVal;
|
||||||
|
val.value.integer = 0;
|
||||||
|
vpi_put_value(callh, &val, 0, vpiNoDelay);
|
||||||
|
vpi_free_object(argv);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the count (optional). */
|
||||||
|
arg = vpi_scan(argv);
|
||||||
|
if (arg) {
|
||||||
|
val.format = vpiIntVal;
|
||||||
|
vpi_get_value(arg, &val);
|
||||||
|
count = val.value.integer;
|
||||||
|
if (count > max-start) {
|
||||||
|
vpi_printf("WARNING: %s:%d: ",
|
||||||
|
vpi_get_str(vpiFile, callh),
|
||||||
|
(int)vpi_get(vpiLineNo, callh));
|
||||||
|
vpi_printf("%s's count argument (%d) is too "
|
||||||
|
"large for start (%d) and memory "
|
||||||
|
"range [%d:%d].\n", name, count,
|
||||||
|
start, left, right);
|
||||||
|
count = max - start + 1;
|
||||||
|
}
|
||||||
|
vpi_free_object(argv);
|
||||||
|
} else {
|
||||||
|
count = max - start + 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
start = min;
|
||||||
|
count = max - min + 1;
|
||||||
|
}
|
||||||
|
width = vpi_get(vpiSize, vpi_handle_by_index(mem_reg, start));
|
||||||
|
} else {
|
||||||
|
start = 0;
|
||||||
|
count = 1;
|
||||||
|
width = vpi_get(vpiSize, mem_reg);
|
||||||
|
vpi_free_object(argv);
|
||||||
|
}
|
||||||
|
|
||||||
|
words = (width+31)/32;
|
||||||
|
vector = calloc(words, sizeof(s_vpi_vecval));
|
||||||
|
bpe = (width+7)/8;
|
||||||
|
|
||||||
|
if (is_mem) {
|
||||||
|
rtn = 0;
|
||||||
|
for (idx = 0; idx < count; idx += 1) {
|
||||||
|
vpiHandle word;
|
||||||
|
word = vpi_handle_by_index(mem_reg, start+(signed)idx);
|
||||||
|
rtn += fread_word(fp, word, words, bpe, vector);
|
||||||
|
if (feof(fp)) break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rtn = fread_word(fp, mem_reg, words, bpe, vector);
|
||||||
|
}
|
||||||
|
free(vector);
|
||||||
|
|
||||||
|
/* Return the number of bytes read. */
|
||||||
|
val.format = vpiIntVal;
|
||||||
|
val.value.integer = rtn;
|
||||||
|
vpi_put_value(callh, &val, 0, vpiNoDelay);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static PLI_INT32 sys_ungetc_calltf(PLI_BYTE8*name)
|
static PLI_INT32 sys_ungetc_calltf(PLI_BYTE8*name)
|
||||||
{
|
{
|
||||||
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
|
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
|
||||||
|
|
@ -437,8 +713,8 @@ static PLI_INT32 sys_ungetc_calltf(PLI_BYTE8*name)
|
||||||
s_vpi_value val;
|
s_vpi_value val;
|
||||||
PLI_UINT32 fd_mcd;
|
PLI_UINT32 fd_mcd;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
unsigned char chr;
|
int chr;
|
||||||
(void) name; /* Not used! */
|
errno = 0;
|
||||||
|
|
||||||
/* Get the character. */
|
/* Get the character. */
|
||||||
arg = vpi_scan(argv);
|
arg = vpi_scan(argv);
|
||||||
|
|
@ -460,6 +736,7 @@ static PLI_INT32 sys_ungetc_calltf(PLI_BYTE8*name)
|
||||||
(int)vpi_get(vpiLineNo, callh));
|
(int)vpi_get(vpiLineNo, callh));
|
||||||
vpi_printf("invalid file descriptor (0x%x) given to %s.\n", fd_mcd,
|
vpi_printf("invalid file descriptor (0x%x) given to %s.\n", fd_mcd,
|
||||||
name);
|
name);
|
||||||
|
errno = EBADF;
|
||||||
val.format = vpiIntVal;
|
val.format = vpiIntVal;
|
||||||
val.value.integer = EOF;
|
val.value.integer = EOF;
|
||||||
vpi_put_value(callh, &val, 0, vpiNoDelay);
|
vpi_put_value(callh, &val, 0, vpiNoDelay);
|
||||||
|
|
@ -469,6 +746,7 @@ static PLI_INT32 sys_ungetc_calltf(PLI_BYTE8*name)
|
||||||
/* ungetc the character and return the result. */
|
/* ungetc the character and return the result. */
|
||||||
val.format = vpiIntVal;
|
val.format = vpiIntVal;
|
||||||
val.value.integer = ungetc(chr, fp);
|
val.value.integer = ungetc(chr, fp);
|
||||||
|
if (val.value.integer != EOF) val.value.integer = 0;
|
||||||
vpi_put_value(callh, &val, 0, vpiNoDelay);
|
vpi_put_value(callh, &val, 0, vpiNoDelay);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -507,7 +785,7 @@ static PLI_INT32 sys_fseek_compiletf(PLI_BYTE8*name)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!arg || !is_numeric_obj(arg)) {
|
if (! is_numeric_obj(arg)) {
|
||||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||||
(int)vpi_get(vpiLineNo, callh));
|
(int)vpi_get(vpiLineNo, callh));
|
||||||
vpi_printf("%s's second argument must be numeric.\n", name);
|
vpi_printf("%s's second argument must be numeric.\n", name);
|
||||||
|
|
@ -524,7 +802,7 @@ static PLI_INT32 sys_fseek_compiletf(PLI_BYTE8*name)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!arg || !is_numeric_obj(arg)) {
|
if (! is_numeric_obj(arg)) {
|
||||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||||
(int)vpi_get(vpiLineNo, callh));
|
(int)vpi_get(vpiLineNo, callh));
|
||||||
vpi_printf("%s's third argument must be numeric.\n", name);
|
vpi_printf("%s's third argument must be numeric.\n", name);
|
||||||
|
|
@ -546,7 +824,7 @@ static PLI_INT32 sys_fseek_calltf(PLI_BYTE8*name)
|
||||||
PLI_UINT32 fd_mcd;
|
PLI_UINT32 fd_mcd;
|
||||||
PLI_INT32 offset, oper;
|
PLI_INT32 offset, oper;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
errno = 0;
|
||||||
|
|
||||||
/* Get the file pointer. */
|
/* Get the file pointer. */
|
||||||
arg = vpi_scan(argv);
|
arg = vpi_scan(argv);
|
||||||
|
|
@ -568,15 +846,22 @@ static PLI_INT32 sys_fseek_calltf(PLI_BYTE8*name)
|
||||||
oper = val.value.integer;
|
oper = val.value.integer;
|
||||||
|
|
||||||
/* Check that the operation is in the valid range. */
|
/* Check that the operation is in the valid range. */
|
||||||
if ((oper < 0) || (oper > 2)) {
|
switch (oper) {
|
||||||
|
case 0:
|
||||||
|
oper = SEEK_SET;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
oper = SEEK_CUR;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
oper = SEEK_END;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh),
|
vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||||
(int)vpi_get(vpiLineNo, callh));
|
(int)vpi_get(vpiLineNo, callh));
|
||||||
vpi_printf("%s's operation must be 0, 1 or 2 given %d.\n",
|
vpi_printf("%s's operation must be 0, 1 or 2 given %d.\n",
|
||||||
name, oper);
|
name, oper);
|
||||||
val.format = vpiIntVal;
|
oper = -1; /* An invalid argument value. */
|
||||||
val.value.integer = EOF;
|
|
||||||
vpi_put_value(callh, &val, 0, vpiNoDelay);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return EOF if this is not a valid fd. */
|
/* Return EOF if this is not a valid fd. */
|
||||||
|
|
@ -586,6 +871,7 @@ static PLI_INT32 sys_fseek_calltf(PLI_BYTE8*name)
|
||||||
(int)vpi_get(vpiLineNo, callh));
|
(int)vpi_get(vpiLineNo, callh));
|
||||||
vpi_printf("invalid file descriptor (0x%x) given to %s.\n", fd_mcd,
|
vpi_printf("invalid file descriptor (0x%x) given to %s.\n", fd_mcd,
|
||||||
name);
|
name);
|
||||||
|
errno = EBADF;
|
||||||
val.format = vpiIntVal;
|
val.format = vpiIntVal;
|
||||||
val.value.integer = EOF;
|
val.value.integer = EOF;
|
||||||
vpi_put_value(callh, &val, 0, vpiNoDelay);
|
vpi_put_value(callh, &val, 0, vpiNoDelay);
|
||||||
|
|
@ -607,6 +893,7 @@ static PLI_INT32 sys_common_fd_calltf(PLI_BYTE8*name)
|
||||||
s_vpi_value val;
|
s_vpi_value val;
|
||||||
PLI_UINT32 fd_mcd;
|
PLI_UINT32 fd_mcd;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
errno = 0;
|
||||||
|
|
||||||
/* Get the file pointer. */
|
/* Get the file pointer. */
|
||||||
arg = vpi_scan(argv);
|
arg = vpi_scan(argv);
|
||||||
|
|
@ -622,6 +909,7 @@ static PLI_INT32 sys_common_fd_calltf(PLI_BYTE8*name)
|
||||||
(int)vpi_get(vpiLineNo, callh));
|
(int)vpi_get(vpiLineNo, callh));
|
||||||
vpi_printf("invalid file descriptor (0x%x) given to %s.\n", fd_mcd,
|
vpi_printf("invalid file descriptor (0x%x) given to %s.\n", fd_mcd,
|
||||||
name);
|
name);
|
||||||
|
errno = EBADF;
|
||||||
val.format = vpiIntVal;
|
val.format = vpiIntVal;
|
||||||
val.value.integer = EOF;
|
val.value.integer = EOF;
|
||||||
vpi_put_value(callh, &val, 0, vpiNoDelay);
|
vpi_put_value(callh, &val, 0, vpiNoDelay);
|
||||||
|
|
@ -654,6 +942,119 @@ static PLI_INT32 sys_common_fd_calltf(PLI_BYTE8*name)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Implement the $ferror system function.
|
||||||
|
*/
|
||||||
|
static PLI_INT32 sys_ferror_compiletf(PLI_BYTE8 *name)
|
||||||
|
{
|
||||||
|
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
|
||||||
|
vpiHandle argv;
|
||||||
|
vpiHandle arg;
|
||||||
|
|
||||||
|
argv = vpi_iterate(vpiArgument, callh);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check that there are two arguments and that the first is
|
||||||
|
* numeric and that the second is a 640 bit or larger register.
|
||||||
|
*
|
||||||
|
* The parser requires that a function have at least one argument,
|
||||||
|
* so argv should always be defined with one argument.
|
||||||
|
*/
|
||||||
|
assert(argv);
|
||||||
|
|
||||||
|
if (! is_numeric_obj(vpi_scan(argv))) {
|
||||||
|
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||||
|
(int)vpi_get(vpiLineNo, callh));
|
||||||
|
vpi_printf("%s's fd (first) argument must be numeric.\n", name);
|
||||||
|
vpi_control(vpiFinish, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check that the second argument is given and that it is a 640 bit
|
||||||
|
* or larger register. */
|
||||||
|
arg = vpi_scan(argv);
|
||||||
|
if (! arg) {
|
||||||
|
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||||
|
(int)vpi_get(vpiLineNo, callh));
|
||||||
|
vpi_printf("%s requires a second (register) argument.\n", name);
|
||||||
|
vpi_control(vpiFinish, 1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vpi_get(vpiType, arg) != vpiReg) {
|
||||||
|
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||||
|
(int)vpi_get(vpiLineNo, callh));
|
||||||
|
vpi_printf("%s's second argument must be a reg (>=640 bits).\n",
|
||||||
|
name);
|
||||||
|
vpi_control(vpiFinish, 1);
|
||||||
|
} else if (vpi_get(vpiSize, arg) < 640) {
|
||||||
|
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||||
|
(int)vpi_get(vpiLineNo, callh));
|
||||||
|
vpi_printf("%s's second argument must have 640 bit or more.\n",
|
||||||
|
name);
|
||||||
|
vpi_control(vpiFinish, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure there are no extra arguments. */
|
||||||
|
check_for_extra_args(argv, callh, name, "two arguments", 0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PLI_INT32 sys_ferror_calltf(PLI_BYTE8 *name)
|
||||||
|
{
|
||||||
|
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
|
||||||
|
vpiHandle argv = vpi_iterate(vpiArgument, callh);
|
||||||
|
vpiHandle reg;
|
||||||
|
s_vpi_value val;
|
||||||
|
char *msg;
|
||||||
|
PLI_INT32 size;
|
||||||
|
unsigned chars;
|
||||||
|
PLI_UINT32 fd_mcd;
|
||||||
|
|
||||||
|
/* Get the file pointer. */
|
||||||
|
val.format = vpiIntVal;
|
||||||
|
vpi_get_value(vpi_scan(argv), &val);
|
||||||
|
fd_mcd = val.value.integer;
|
||||||
|
|
||||||
|
/* Get the register to put the string result and figure out how many
|
||||||
|
* characters it will hold. */
|
||||||
|
reg = vpi_scan(argv);
|
||||||
|
size = vpi_get(vpiSize, reg);
|
||||||
|
chars = size / 8;
|
||||||
|
vpi_free_object(argv);
|
||||||
|
|
||||||
|
/* If we do not already have an error check that the fd is valid.
|
||||||
|
* The assumption is that the other routines have set errno to
|
||||||
|
* EBADF when they encounter a bad file descriptor, so we do not
|
||||||
|
* need to check here. We also need to special case this since
|
||||||
|
* $fopen() will return 0 (a bad file descriptor) when it has a
|
||||||
|
* problem (sets errno). */
|
||||||
|
if (!errno && !vpi_get_file(fd_mcd) ) {
|
||||||
|
vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||||
|
(int)vpi_get(vpiLineNo, callh));
|
||||||
|
vpi_printf("invalid file descriptor (0x%x) given to %s.\n", fd_mcd,
|
||||||
|
name);
|
||||||
|
errno = EBADF;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the error code. */
|
||||||
|
val.format = vpiIntVal;
|
||||||
|
val.value.integer = errno;
|
||||||
|
vpi_put_value(callh, &val, 0, vpiNoDelay);
|
||||||
|
|
||||||
|
/* Only return the number of characters that will fit in the reg. */
|
||||||
|
msg = (char *) malloc(chars);
|
||||||
|
if (errno != 0) strncpy(msg, strerror(errno), chars-1);
|
||||||
|
else strncpy(msg, "", chars-1);
|
||||||
|
msg[chars-1] = '\0';
|
||||||
|
val.format = vpiStringVal;
|
||||||
|
val.value.str = msg;
|
||||||
|
vpi_put_value(reg, &val, 0, vpiNoDelay);
|
||||||
|
free(msg);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void sys_fileio_register()
|
void sys_fileio_register()
|
||||||
{
|
{
|
||||||
s_vpi_systf_data tf_data;
|
s_vpi_systf_data tf_data;
|
||||||
|
|
@ -706,15 +1107,6 @@ void sys_fileio_register()
|
||||||
tf_data.user_data = "$fflush";
|
tf_data.user_data = "$fflush";
|
||||||
vpi_register_systf(&tf_data);
|
vpi_register_systf(&tf_data);
|
||||||
|
|
||||||
/*============================== fputc */
|
|
||||||
tf_data.type = vpiSysTask;
|
|
||||||
tf_data.tfname = "$fputc";
|
|
||||||
tf_data.calltf = sys_fputc_calltf;
|
|
||||||
tf_data.compiletf = sys_two_numeric_args_compiletf;
|
|
||||||
tf_data.sizetf = 0;
|
|
||||||
tf_data.user_data = "$fputc";
|
|
||||||
vpi_register_systf(&tf_data);
|
|
||||||
|
|
||||||
/*============================== fgetc */
|
/*============================== fgetc */
|
||||||
tf_data.type = vpiSysFunc;
|
tf_data.type = vpiSysFunc;
|
||||||
tf_data.sysfunctype = vpiIntFunc;
|
tf_data.sysfunctype = vpiIntFunc;
|
||||||
|
|
@ -735,6 +1127,16 @@ void sys_fileio_register()
|
||||||
tf_data.user_data = "$fgets";
|
tf_data.user_data = "$fgets";
|
||||||
vpi_register_systf(&tf_data);
|
vpi_register_systf(&tf_data);
|
||||||
|
|
||||||
|
/*============================== fread */
|
||||||
|
tf_data.type = vpiSysFunc;
|
||||||
|
tf_data.sysfunctype = vpiIntFunc;
|
||||||
|
tf_data.tfname = "$fread";
|
||||||
|
tf_data.calltf = sys_fread_calltf;
|
||||||
|
tf_data.compiletf = sys_fread_compiletf;
|
||||||
|
tf_data.sizetf = 0;
|
||||||
|
tf_data.user_data = "$fread";
|
||||||
|
vpi_register_systf(&tf_data);
|
||||||
|
|
||||||
/*============================== ungetc */
|
/*============================== ungetc */
|
||||||
tf_data.type = vpiSysFunc;
|
tf_data.type = vpiSysFunc;
|
||||||
tf_data.sysfunctype = vpiIntFunc;
|
tf_data.sysfunctype = vpiIntFunc;
|
||||||
|
|
@ -775,7 +1177,17 @@ void sys_fileio_register()
|
||||||
tf_data.user_data = "$rewind";
|
tf_data.user_data = "$rewind";
|
||||||
vpi_register_systf(&tf_data);
|
vpi_register_systf(&tf_data);
|
||||||
|
|
||||||
/* $feof() is from 1364-2005. */
|
/*============================== ferror */
|
||||||
|
tf_data.type = vpiSysFunc;
|
||||||
|
tf_data.sysfunctype = vpiIntFunc;
|
||||||
|
tf_data.tfname = "$ferror";
|
||||||
|
tf_data.calltf = sys_ferror_calltf;
|
||||||
|
tf_data.compiletf = sys_ferror_compiletf;
|
||||||
|
tf_data.sizetf = 0;
|
||||||
|
tf_data.user_data = "$ferror";
|
||||||
|
vpi_register_systf(&tf_data);
|
||||||
|
|
||||||
|
/* $feof() is from 1364-2005. */
|
||||||
/*============================== feof */
|
/*============================== feof */
|
||||||
tf_data.type = vpiSysFunc;
|
tf_data.type = vpiSysFunc;
|
||||||
tf_data.sysfunctype = vpiIntFunc;
|
tf_data.sysfunctype = vpiIntFunc;
|
||||||
|
|
@ -786,4 +1198,14 @@ void sys_fileio_register()
|
||||||
tf_data.user_data = "$feof";
|
tf_data.user_data = "$feof";
|
||||||
vpi_register_systf(&tf_data);
|
vpi_register_systf(&tf_data);
|
||||||
|
|
||||||
|
/* Icarus specific. */
|
||||||
|
/*============================== fputc */
|
||||||
|
tf_data.type = vpiSysFunc;
|
||||||
|
tf_data.sysfunctype = vpiIntFunc;
|
||||||
|
tf_data.tfname = "$fputc";
|
||||||
|
tf_data.calltf = sys_fputc_calltf;
|
||||||
|
tf_data.compiletf = sys_two_numeric_args_compiletf;
|
||||||
|
tf_data.sizetf = 0;
|
||||||
|
tf_data.user_data = "$fputc";
|
||||||
|
vpi_register_systf(&tf_data);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
112
vpi/sys_icarus.c
112
vpi/sys_icarus.c
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2008 Cary R. (cygcary@yahoo.com)
|
* Copyright (C) 2008-2009 Cary R. (cygcary@yahoo.com)
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
|
@ -53,11 +53,15 @@ static PLI_INT32 task_not_implemented_compiletf(PLI_BYTE8* name)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PLI_INT32 function_not_implemented_compiletf(PLI_BYTE8* name)
|
/*
|
||||||
|
* This is used to warn the user that the specified optional system
|
||||||
|
* task/function is not available (from Annex C 1364-2005).
|
||||||
|
*/
|
||||||
|
static PLI_INT32 missing_optional_compiletf(PLI_BYTE8* name)
|
||||||
{
|
{
|
||||||
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
|
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
|
||||||
|
|
||||||
vpi_printf("%s:%d: SORRY: function %s() is not currently implemented.\n",
|
vpi_printf("%s:%d: SORRY: %s() is not available in Icarus verilog.\n",
|
||||||
vpi_get_str(vpiFile, callh), (int)vpi_get(vpiLineNo, callh),
|
vpi_get_str(vpiFile, callh), (int)vpi_get(vpiLineNo, callh),
|
||||||
name);
|
name);
|
||||||
vpi_control(vpiFinish, 1);
|
vpi_control(vpiFinish, 1);
|
||||||
|
|
@ -185,16 +189,106 @@ void sys_special_register(void)
|
||||||
tf_data.user_data = "$q_exam";
|
tf_data.user_data = "$q_exam";
|
||||||
vpi_register_systf(&tf_data);
|
vpi_register_systf(&tf_data);
|
||||||
|
|
||||||
/* These functions are not currently implemented. */
|
tf_data.tfname = "$dumpports";
|
||||||
tf_data.compiletf = function_not_implemented_compiletf;
|
tf_data.user_data = "$dumpports";
|
||||||
|
vpi_register_systf(&tf_data);
|
||||||
|
|
||||||
|
tf_data.tfname = "$dumpportsoff";
|
||||||
|
tf_data.user_data = "$dumpportsoff";
|
||||||
|
vpi_register_systf(&tf_data);
|
||||||
|
|
||||||
|
tf_data.tfname = "$dumpportson";
|
||||||
|
tf_data.user_data = "$dumpportson";
|
||||||
|
vpi_register_systf(&tf_data);
|
||||||
|
|
||||||
|
tf_data.tfname = "$dumpportsall";
|
||||||
|
tf_data.user_data = "$dumpportsall";
|
||||||
|
vpi_register_systf(&tf_data);
|
||||||
|
|
||||||
|
tf_data.tfname = "$dumpportslimit";
|
||||||
|
tf_data.user_data = "$dumpportslimit";
|
||||||
|
vpi_register_systf(&tf_data);
|
||||||
|
|
||||||
|
tf_data.tfname = "$dumpportsflush";
|
||||||
|
tf_data.user_data = "$dumpportsflush";
|
||||||
|
vpi_register_systf(&tf_data);
|
||||||
|
|
||||||
|
/* The following optional system tasks/functions are not implemented
|
||||||
|
* in Icarus Verilog (from Annex C 1364-2005). */
|
||||||
|
tf_data.type = vpiSysTask;
|
||||||
|
tf_data.calltf = 0;
|
||||||
|
tf_data.sizetf = 0;
|
||||||
|
tf_data.compiletf = missing_optional_compiletf;
|
||||||
|
|
||||||
|
tf_data.tfname = "$input";
|
||||||
|
tf_data.user_data = "$input";
|
||||||
|
vpi_register_systf(&tf_data);
|
||||||
|
|
||||||
|
tf_data.tfname = "$key";
|
||||||
|
tf_data.user_data = "$key";
|
||||||
|
vpi_register_systf(&tf_data);
|
||||||
|
|
||||||
|
tf_data.tfname = "$nokey";
|
||||||
|
tf_data.user_data = "$nokey";
|
||||||
|
vpi_register_systf(&tf_data);
|
||||||
|
|
||||||
|
tf_data.tfname = "$list";
|
||||||
|
tf_data.user_data = "$list";
|
||||||
|
vpi_register_systf(&tf_data);
|
||||||
|
|
||||||
|
tf_data.tfname = "$log";
|
||||||
|
tf_data.user_data = "$log";
|
||||||
|
vpi_register_systf(&tf_data);
|
||||||
|
|
||||||
|
tf_data.tfname = "$nolog";
|
||||||
|
tf_data.user_data = "$nolog";
|
||||||
|
vpi_register_systf(&tf_data);
|
||||||
|
|
||||||
|
tf_data.tfname = "$save";
|
||||||
|
tf_data.user_data = "$save";
|
||||||
|
vpi_register_systf(&tf_data);
|
||||||
|
|
||||||
|
tf_data.tfname = "$restart";
|
||||||
|
tf_data.user_data = "$restart";
|
||||||
|
vpi_register_systf(&tf_data);
|
||||||
|
|
||||||
|
tf_data.tfname = "$incsave";
|
||||||
|
tf_data.user_data = "$incsave";
|
||||||
|
vpi_register_systf(&tf_data);
|
||||||
|
|
||||||
|
tf_data.tfname = "$scope";
|
||||||
|
tf_data.user_data = "$scope";
|
||||||
|
vpi_register_systf(&tf_data);
|
||||||
|
|
||||||
|
tf_data.tfname = "$showscopes";
|
||||||
|
tf_data.user_data = "$showscopes";
|
||||||
|
vpi_register_systf(&tf_data);
|
||||||
|
|
||||||
|
tf_data.tfname = "$showvars";
|
||||||
|
tf_data.user_data = "$showvars";
|
||||||
|
vpi_register_systf(&tf_data);
|
||||||
|
|
||||||
|
tf_data.tfname = "$sreadmemb";
|
||||||
|
tf_data.user_data = "$sreadmemb";
|
||||||
|
vpi_register_systf(&tf_data);
|
||||||
|
|
||||||
|
tf_data.tfname = "$sreadmemh";
|
||||||
|
tf_data.user_data = "$sreadmemh";
|
||||||
|
vpi_register_systf(&tf_data);
|
||||||
|
|
||||||
|
/* Optional functions. */
|
||||||
tf_data.type = vpiSysFunc;
|
tf_data.type = vpiSysFunc;
|
||||||
tf_data.sysfunctype = vpiIntFunc;
|
tf_data.sysfunctype = vpiIntFunc;
|
||||||
|
|
||||||
tf_data.tfname = "$ferror";
|
tf_data.tfname = "$countdrivers";
|
||||||
tf_data.user_data = "$ferror";
|
tf_data.user_data = "$countdrivers";
|
||||||
vpi_register_systf(&tf_data);
|
vpi_register_systf(&tf_data);
|
||||||
|
|
||||||
tf_data.tfname = "$fread";
|
tf_data.tfname = "$getpattern";
|
||||||
tf_data.user_data = "$fread";
|
tf_data.user_data = "$getpattern";
|
||||||
|
vpi_register_systf(&tf_data);
|
||||||
|
|
||||||
|
tf_data.tfname = "$scale";
|
||||||
|
tf_data.user_data = "$scale";
|
||||||
vpi_register_systf(&tf_data);
|
vpi_register_systf(&tf_data);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,10 +17,9 @@
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
# include "sys_priv.h"
|
|
||||||
# include "lxt_write.h"
|
# include "lxt_write.h"
|
||||||
# include "vcd_priv.h"
|
|
||||||
# include "sys_priv.h"
|
# include "sys_priv.h"
|
||||||
|
# include "vcd_priv.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This file contains the implementations of the LXT related
|
* This file contains the implementations of the LXT related
|
||||||
|
|
@ -39,6 +38,29 @@
|
||||||
# include "stringheap.h"
|
# include "stringheap.h"
|
||||||
|
|
||||||
|
|
||||||
|
static char *dump_path = NULL;
|
||||||
|
static struct lt_trace *dump_file = NULL;
|
||||||
|
|
||||||
|
struct vcd_info {
|
||||||
|
vpiHandle item;
|
||||||
|
vpiHandle cb;
|
||||||
|
struct t_vpi_time time;
|
||||||
|
struct lt_symbol *sym;
|
||||||
|
struct vcd_info *next;
|
||||||
|
struct vcd_info *dmp_next;
|
||||||
|
int scheduled;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static struct vcd_info *vcd_list = NULL;
|
||||||
|
static struct vcd_info *vcd_dmp_list = NULL;
|
||||||
|
static PLI_UINT64 vcd_cur_time = 0;
|
||||||
|
static int dump_is_off = 0;
|
||||||
|
static long dump_limit = 0;
|
||||||
|
static int dump_is_full = 0;
|
||||||
|
static int finish_status = 0;
|
||||||
|
|
||||||
|
|
||||||
static enum lxm_optimum_mode_e {
|
static enum lxm_optimum_mode_e {
|
||||||
LXM_NONE = 0,
|
LXM_NONE = 0,
|
||||||
LXM_SPACE = 1,
|
LXM_SPACE = 1,
|
||||||
|
|
@ -140,30 +162,6 @@ static char *create_full_name(const char *name)
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static char *dump_path = 0;
|
|
||||||
static struct lt_trace *dump_file = 0;
|
|
||||||
|
|
||||||
struct vcd_info {
|
|
||||||
vpiHandle item;
|
|
||||||
vpiHandle cb;
|
|
||||||
struct t_vpi_time time;
|
|
||||||
struct lt_symbol *sym;
|
|
||||||
struct vcd_info *next;
|
|
||||||
struct vcd_info *dmp_next;
|
|
||||||
int scheduled;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
static struct vcd_info*vcd_list = 0;
|
|
||||||
static struct vcd_info*vcd_dmp_list = 0;
|
|
||||||
static PLI_UINT64 vcd_cur_time = 0;
|
|
||||||
static int dump_is_off = 0;
|
|
||||||
static long dump_limit = 0;
|
|
||||||
static int dump_is_full = 0;
|
|
||||||
static int finish_status = 0;
|
|
||||||
|
|
||||||
|
|
||||||
static void show_this_item(struct vcd_info*info)
|
static void show_this_item(struct vcd_info*info)
|
||||||
{
|
{
|
||||||
s_vpi_value value;
|
s_vpi_value value;
|
||||||
|
|
@ -297,6 +295,8 @@ static PLI_INT32 dumpvars_cb(p_cb_data cause)
|
||||||
|
|
||||||
static PLI_INT32 finish_cb(p_cb_data cause)
|
static PLI_INT32 finish_cb(p_cb_data cause)
|
||||||
{
|
{
|
||||||
|
struct vcd_info *cur, *next;
|
||||||
|
|
||||||
if (finish_status != 0) return 0;
|
if (finish_status != 0) return 0;
|
||||||
|
|
||||||
finish_status = 1;
|
finish_status = 1;
|
||||||
|
|
@ -306,6 +306,17 @@ static PLI_INT32 finish_cb(p_cb_data cause)
|
||||||
lt_set_time64(dump_file, dumpvars_time);
|
lt_set_time64(dump_file, dumpvars_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (cur = vcd_list ; cur ; cur = next) {
|
||||||
|
next = cur->next;
|
||||||
|
free(cur);
|
||||||
|
}
|
||||||
|
vcd_list = 0;
|
||||||
|
|
||||||
|
vcd_names_delete(&lxt_tab);
|
||||||
|
nexus_ident_delete();
|
||||||
|
free(dump_path);
|
||||||
|
dump_path = 0;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -421,7 +432,8 @@ static PLI_INT32 sys_dumpall_calltf(PLI_BYTE8*name)
|
||||||
static void *close_dumpfile(void)
|
static void *close_dumpfile(void)
|
||||||
{
|
{
|
||||||
lt_close(dump_file);
|
lt_close(dump_file);
|
||||||
return (dump_file = NULL);
|
dump_file = NULL;
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void open_dumpfile(vpiHandle callh)
|
static void open_dumpfile(vpiHandle callh)
|
||||||
|
|
@ -538,11 +550,27 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
|
||||||
switch (vpi_get(vpiType, item)) {
|
switch (vpi_get(vpiType, item)) {
|
||||||
|
|
||||||
case vpiNet: type = "wire"; if(0){
|
case vpiNet: type = "wire"; if(0){
|
||||||
case vpiIntegerVar:
|
|
||||||
case vpiMemoryWord:
|
case vpiMemoryWord:
|
||||||
|
if (vpi_get(vpiConstantSelect, item) == 0) {
|
||||||
|
/* Turn a non-constant array word select into a
|
||||||
|
* constant word select. */
|
||||||
|
vpiHandle array = vpi_handle(vpiParent, item);
|
||||||
|
PLI_INT32 index = vpi_get(vpiIndex, item);
|
||||||
|
item = vpi_handle_by_index(array, index);
|
||||||
|
}
|
||||||
|
case vpiIntegerVar:
|
||||||
case vpiTimeVar:
|
case vpiTimeVar:
|
||||||
case vpiReg: type = "reg"; }
|
case vpiReg: type = "reg"; }
|
||||||
|
|
||||||
|
/* An array word is implicitly escaped so look for an
|
||||||
|
* escaped identifier that this could conflict with. */
|
||||||
|
if (vpi_get(vpiType, item) == vpiMemoryWord &&
|
||||||
|
vpi_handle_by_name(vpi_get_str(vpiFullName, item), 0)) {
|
||||||
|
vpi_printf("LXT warning: dumping array word %s will "
|
||||||
|
"conflict with an escaped identifier.\n",
|
||||||
|
vpi_get_str(vpiFullName, item));
|
||||||
|
}
|
||||||
|
|
||||||
if (skip || vpi_get(vpiAutomatic, item)) break;
|
if (skip || vpi_get(vpiAutomatic, item)) break;
|
||||||
|
|
||||||
name = vpi_get_str(vpiName, item);
|
name = vpi_get_str(vpiName, item);
|
||||||
|
|
@ -563,12 +591,12 @@ static void scan_item(unsigned depth, vpiHandle item, int skip)
|
||||||
info = malloc(sizeof(*info));
|
info = malloc(sizeof(*info));
|
||||||
|
|
||||||
info->time.type = vpiSimTime;
|
info->time.type = vpiSimTime;
|
||||||
info->item = item;
|
info->item = item;
|
||||||
info->sym = lt_symbol_add(dump_file, ident,
|
info->sym = lt_symbol_add(dump_file, ident,
|
||||||
0 /* array rows */,
|
0 /* array rows */,
|
||||||
vpi_get(vpiLeftRange, item),
|
vpi_get(vpiLeftRange, item),
|
||||||
vpi_get(vpiRightRange, item),
|
vpi_get(vpiRightRange, item),
|
||||||
LT_SYM_F_BITS);
|
LT_SYM_F_BITS);
|
||||||
info->scheduled = 0;
|
info->scheduled = 0;
|
||||||
|
|
||||||
cb.time = &info->time;
|
cb.time = &info->time;
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue