Merge branch 'master' of git://icarus.com/~steve-icarus/verilog into vhdl

Conflicts:

	tgt-vhdl/stmt.cc
This commit is contained in:
Nick Gasson 2008-10-05 12:44:30 +01:00
commit 4394aff909
136 changed files with 5579 additions and 6126 deletions

View File

@ -18,6 +18,23 @@
#
SHELL = /bin/sh
# Normally, the "make" will build all the files only by dependencies.
# The MODE, however, can control your rebuild intentions. The proper way
# to use the MODE is on the make command like, this this:
#
# make MODE=XXXX all
#
# The possible MODE= values are:
#
# regular
# Build as normal
#
# full
# Do some extra builds. in particular:
# Build version.h again, even if it already exists.
#
MODE=regular
# This version string is only used in the version message printed
# by the compiler. It reflects the assigned version number for the
# product as a whole. Most components also print the CVS Name: token
@ -52,15 +69,15 @@ MAN = @MAN@
PS2PDF = @PS2PDF@
GIT = @GIT@
CPPFLAGS = @ident_support@ @DEFS@ -I. -I$(srcdir) @CPPFLAGS@
CPPFLAGS = @ident_support@ @DEFS@ -I. -I$(srcdir) -DVERSION='"$(VERSION)"' @CPPFLAGS@
CXXFLAGS = -Wall @CXXFLAGS@
PICFLAGS = @PICFLAG@
LDFLAGS = @rdynamic@ @LDFLAGS@
all: dep version.h ivl@EXEEXT@
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) $@); done
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) VERSION=$(VERSION) $@); done
for dir in ivlpp ; \
do (cd $$dir ; $(MAKE) $@); done
do (cd $$dir ; $(MAKE) VERSION=$(VERSION) $@); done
cd driver ; $(MAKE) VERSION=$(VERSION) $@
# In the windows world, the installer will need a dosify program to
@ -110,7 +127,7 @@ net_proc.o net_scope.o net_tran.o net_udp.o pad_to_width.o \
parse.o parse_misc.o pform.o pform_analog.o pform_disciplines.o \
pform_dump.o pform_types.o \
set_width.o symbol_search.o sync.o sys_funcs.o \
verinum.o verireal.o target.o targets.o \
verinum.o verireal.o target.o \
Attrib.o HName.o LineInfo.o Module.o PDelays.o PEvent.o \
PExpr.o PGate.o PGenerate.o PScope.o PSpec.o \
PTask.o PUdp.o PFunction.o PWire.o Statement.o AStatement.o StringHeap.o \
@ -186,7 +203,9 @@ iverilog-vpi.pdf: iverilog-vpi.ps
# For VERSION_TAG in driver/main.c, first try git-describe, then look for a
# version.h file in the source tree (included in snapshots and releases), and
# finally use nothing.
ifeq ($(MODE),full)
.PHONY: version.h
endif
# "true" and "false" in the next few lines are Unix shell command names
ifeq ($(GIT),none)
GIT_PRESENT = false

View File

@ -76,40 +76,6 @@ class Module : public PScope, public LineInfo {
NetNet::Type default_nettype;
struct range_t {
// True if this is an exclude
bool exclude_flag;
// lower bound
// If low_open_flag is false and low_expr=0, then use -inf
bool low_open_flag;
PExpr*low_expr;
// upper bound
// If high_open_flag is false and high_expr=0, then use +inf
bool high_open_flag;
PExpr*high_expr;
// Next range description in list
struct range_t*next;
};
/* The module has parameters that are evaluated when the
module is elaborated. During parsing, I put the parameters
into this map. */
struct param_expr_t : public LineInfo {
param_expr_t() : type(IVL_VT_NO_TYPE), msb(0), lsb(0), signed_flag(false), expr(0), range(0) { }
// Type information
ivl_variable_type_t type;
PExpr*msb;
PExpr*lsb;
bool signed_flag;
// Value expression
PExpr*expr;
// If there are range constraints, list them here
range_t*range;
};
map<perm_string,param_expr_t>parameters;
map<perm_string,param_expr_t>localparams;
/* specparams are simpler then other params, in that they have
no type information. They are merely constant
expressions. */

View File

@ -101,7 +101,7 @@ static NetExpr*calculate_val(Design*des, NetScope*scope, const PExpr*expr)
return dex;
}
static NetExpr* make_delay_nets(Design*des, NetExpr*expr)
static NetExpr* make_delay_nets(Design*des, NetScope*scope, NetExpr*expr)
{
if (dynamic_cast<NetESignal*> (expr))
return expr;
@ -109,7 +109,7 @@ static NetExpr* make_delay_nets(Design*des, NetExpr*expr)
if (dynamic_cast<NetEConst*> (expr))
return expr;
NetNet*sig = expr->synthesize(des);
NetNet*sig = expr->synthesize(des, scope);
if (sig == 0) {
cerr << expr->get_fileline() << ": error: Expression " << *expr
<< " is not suitable for delay expression." << endl;
@ -132,17 +132,17 @@ void PDelays::eval_delays(Design*des, NetScope*scope,
if (delay_[0]) {
rise_time = calculate_val(des, scope, delay_[0]);
if (as_nets_flag)
rise_time = make_delay_nets(des, rise_time);
rise_time = make_delay_nets(des, scope, rise_time);
if (delay_[1]) {
fall_time = calculate_val(des, scope, delay_[1]);
if (as_nets_flag)
fall_time = make_delay_nets(des, fall_time);
fall_time = make_delay_nets(des, scope, fall_time);
if (delay_[2]) {
decay_time = calculate_val(des, scope, delay_[2]);
if (as_nets_flag)
decay_time = make_delay_nets(des, decay_time);
decay_time = make_delay_nets(des, scope, decay_time);
} else {
if (rise_time < fall_time)

246
PExpr.h
View File

@ -36,9 +36,6 @@ class NetScope;
* The PExpr class hierarchy supports the description of
* expressions. The parser can generate expression objects from the
* source, possibly reducing things that it knows how to reduce.
*
* The elaborate_net method is used by structural elaboration to build
* up a netlist interpretation of the expression.
*/
class PExpr : public LineInfo {
@ -53,7 +50,7 @@ class PExpr : public LineInfo {
// be. It is used by elaboration of assignments to figure out
// the width of the expression.
//
// The "min" is the width of the local context, so it the
// The "min" is the width of the local context, so is the
// minimum width that this function should return. Initially
// this is the same as the lval width.
//
@ -66,12 +63,16 @@ class PExpr : public LineInfo {
// the subexpression should not make l-value related
// optimizations.
//
// The expr_type is an output argument that gives the
// calculated type for the expression.
//
// The unsigned_flag is set to true if the expression is
// unsized and therefore expandable. This happens if a
// sub-expression is an unsized literal. Some expressions make
// special use of that.
virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
bool&unsized_flag) const;
// During the elaborate_sig phase, we may need to scan
@ -98,17 +99,6 @@ class PExpr : public LineInfo {
// evaluation of parameters.
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
// This method elaborate the expression as gates, for use in a
// continuous assign or other wholly structural context.
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned lwidth,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0 =Link::STRONG,
Link::strength_t drive1 =Link::STRONG)
const;
// This method elaborates the expression as gates, but
// restricted for use as l-values of continuous assignments.
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope) const;
@ -163,13 +153,6 @@ class PEConcat : public PExpr {
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope) const;
virtual NetNet* elaborate_bi_net(Design*des, NetScope*scope) const;
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned width,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
int expr_width, bool sys_task_arg) const;
virtual NetEConcat*elaborate_pexpr(Design*des, NetScope*) const;
@ -232,18 +215,14 @@ class PEFNumber : public PExpr {
/* A PEFNumber is a constant, so this returns true. */
virtual bool is_constant(Module*) const;
virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
bool&unsized_flag) const;
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
int expr_width, bool sys_task_arg) const;
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned lwidth,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
virtual void dump(ostream&) const;
private:
@ -264,6 +243,7 @@ class PEIdent : public PExpr {
virtual void dump(ostream&) const;
virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
bool&unsized_flag) const;
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
@ -278,15 +258,6 @@ class PEIdent : public PExpr {
NetScope*scope,
bool is_force) const;
// Structural r-values are OK.
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned lwidth,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
int expr_width, bool sys_task_arg) const;
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
@ -321,12 +292,13 @@ class PEIdent : public PExpr {
index_component_t::ctype_t) const;
private:
NetExpr*elaborate_expr_param(Design*des,
NetScope*scope,
const NetExpr*par,
NetScope*found,
const NetExpr*par_msb,
const NetExpr*par_lsb) const;
NetExpr*elaborate_expr_param_(Design*des,
NetScope*scope,
const NetExpr*par,
NetScope*found,
const NetExpr*par_msb,
const NetExpr*par_lsb,
int expr_wid) const;
NetExpr*elaborate_expr_param_part_(Design*des,
NetScope*scope,
const NetExpr*par,
@ -366,38 +338,6 @@ class PEIdent : public PExpr {
NetESignal*net,
NetScope*found) const;
public:
NetNet* elaborate_net_array_(Design*des, NetScope*scope,
NetNet*sig, unsigned lwidth,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
NetNet* elaborate_net_net_(Design*des, NetScope*scope,
NetNet*sig, unsigned lwidth,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
NetNet* elaborate_net_net_idx_up_(Design*des, NetScope*scope,
NetNet*sig, unsigned lwidth,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
NetNet* elaborate_net_bitmux_(Design*des, NetScope*scope,
NetNet*sig,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
private:
NetNet* elaborate_lnet_common_(Design*des, NetScope*scope,
bool bidirectional_flag) const;
@ -406,8 +346,6 @@ class PEIdent : public PExpr {
bool eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
long&midx, long&lidx) const;
NetNet*process_select_(Design*des, NetScope*scope, NetNet*sig) const;
};
class PENumber : public PExpr {
@ -421,15 +359,9 @@ class PENumber : public PExpr {
virtual void dump(ostream&) const;
virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
bool&unsized_flag) const;
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned lwidth,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
virtual NetEConst*elaborate_expr(Design*des, NetScope*,
int expr_width, bool) const;
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
@ -464,15 +396,9 @@ class PEString : public PExpr {
virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
bool&unsized_flag) const;
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned width,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
virtual NetEConst*elaborate_expr(Design*des, NetScope*,
int expr_width, bool) const;
virtual NetEConst*elaborate_pexpr(Design*des, NetScope*sc) const;
@ -492,15 +418,13 @@ class PEUnary : public PExpr {
virtual void dump(ostream&out) const;
virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
bool&unsized_flag) const;
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned width,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
int expr_width, bool sys_task_arg) const;
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
@ -508,32 +432,6 @@ class PEUnary : public PExpr {
virtual bool is_constant(Module*) const;
private:
NetNet* elab_net_uminus_const_logic_(Design*des, NetScope*scope,
NetEConst*expr,
unsigned width,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
NetNet* elab_net_uminus_const_real_(Design*des, NetScope*scope,
NetECReal*expr,
unsigned width,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
NetNet* elab_net_unary_real_(Design*des, NetScope*scope,
NetExpr*expr,
unsigned width,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
private:
char op_;
PExpr*expr_;
@ -551,17 +449,11 @@ class PEBinary : public PExpr {
virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
bool&unsized_flag) const;
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned width,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
int expr_width, bool sys_task_arg) const;
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
@ -575,54 +467,15 @@ class PEBinary : public PExpr {
NetExpr*elaborate_expr_base_(Design*, NetExpr*lp, NetExpr*rp, int use_wid) const;
NetExpr*elaborate_eval_expr_base_(Design*, NetExpr*lp, NetExpr*rp, int use_wid) const;
NetExpr*elaborate_expr_base_bits_(Design*, NetExpr*lp, NetExpr*rp, int use_wid) const;
NetExpr*elaborate_expr_base_div_(Design*, NetExpr*lp, NetExpr*rp, int use_wid) const;
NetExpr*elaborate_expr_base_lshift_(Design*, NetExpr*lp, NetExpr*rp, int use_wid) const;
NetExpr*elaborate_expr_base_rshift_(Design*, NetExpr*lp, NetExpr*rp, int use_wid) const;
NetExpr*elaborate_expr_base_mult_(Design*, NetExpr*lp, NetExpr*rp, int use_wid) const;
NetExpr*elaborate_expr_base_add_(Design*, NetExpr*lp, NetExpr*rp, int use_wid) const;
static void suppress_operand_sign_if_needed_(NetExpr*lp, NetExpr*rp);
private:
NetNet* elaborate_net_add_(Design*des, NetScope*scope,
unsigned lwidth,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay) const;
NetNet* elaborate_net_bit_(Design*des, NetScope*scope,
unsigned lwidth,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay) const;
NetNet* elaborate_net_cmp_(Design*des, NetScope*scope,
unsigned lwidth,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay) const;
NetNet* elaborate_net_div_(Design*des, NetScope*scope,
unsigned lwidth,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay) const;
NetNet* elaborate_net_mod_(Design*des, NetScope*scope,
unsigned lwidth,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay) const;
NetNet* elaborate_net_log_(Design*des, NetScope*scope,
unsigned lwidth,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay) const;
NetNet* elaborate_net_mul_(Design*des, NetScope*scope,
unsigned lwidth,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay) const;
NetNet* elaborate_net_pow_(Design*des, NetScope*scope,
unsigned lwidth,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay) const;
NetNet* elaborate_net_shift_(Design*des, NetScope*scope,
unsigned lwidth,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay) const;
};
/*
@ -637,6 +490,7 @@ class PEBComp : public PEBinary {
virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
bool&flag) const;
NetExpr* elaborate_expr(Design*des, NetScope*scope,
@ -650,7 +504,11 @@ class PEBShift : public PEBinary {
~PEBShift();
virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval, bool&flag) const;
unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
bool&flag) const;
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
int expr_width, bool sys_task_arg) const;
};
/*
@ -668,18 +526,12 @@ class PETernary : public PExpr {
virtual void dump(ostream&out) const;
virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
bool&unsized_flag) const;
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned width,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
virtual NetETernary*elaborate_expr(Design*des, NetScope*,
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
int expr_width, bool sys_task_arg) const;
virtual NetETernary*elaborate_pexpr(Design*des, NetScope*sc) const;
virtual verinum* eval_const(Design*des, NetScope*sc) const;
@ -712,19 +564,13 @@ class PECallFunction : public PExpr {
virtual void dump(ostream &) const;
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned width,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
int expr_wid, bool sys_task_arg) const;
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
bool&unsized_flag) const;
private:
@ -735,15 +581,9 @@ class PECallFunction : public PExpr {
NetExpr* elaborate_sfunc_(Design*des, NetScope*scope, int expr_wid) const;
NetExpr* elaborate_access_func_(Design*des, NetScope*scope, int expr_wid) const;
NetNet* elaborate_net_sfunc_(Design*des, NetScope*scope,
unsigned width,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
unsigned test_width_sfunc_(Design*des, NetScope*scope,
unsigned min, unsigned lval,
ivl_variable_type_t&expr_type,
bool&unsized_flag) const;
};

12
PGate.h
View File

@ -167,8 +167,16 @@ class PGBuiltin : public PGate {
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
private:
Type type_;
unsigned calculate_array_count_(Design*, NetScope*,
long&high, long&low) const;
unsigned calculate_output_count_(void) const;
NetNode* create_gate_for_output_(Design*, NetScope*,
perm_string gate_name,
unsigned instance_width) const;
Type type_;
PExpr*msb_;
PExpr*lsb_;
};
@ -239,7 +247,7 @@ class PGModule : public PGate {
NetNet*resize_net_to_port_(Design*des, NetScope*scope,
NetNet*sig, unsigned port_wid,
NetNet::PortType dir) const;
NetNet::PortType dir, bool as_signed) const;
};
#endif

View File

@ -78,8 +78,6 @@ class PGenerate : public LineInfo, public LexicalScope {
list<PGate*> gates;
void add_gate(PGate*);
list<PProcess*> behaviors;
// Tasks instantiated within this scheme.
map<perm_string,PTask*> tasks;
map<perm_string,PFunction*>funcs;

View File

@ -19,11 +19,14 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
# include "LineInfo.h"
# include "StringHeap.h"
# include "pform_types.h"
# include "ivl_target.h"
# include <map>
class PEvent;
class PExpr;
class AProcess;
class PProcess;
class PWire;
@ -36,7 +39,7 @@ class NetScope;
* represents lexical scope. For example, a module, a function/task, a
* named block is derived from a PScope.
*
* NOTE: This is note the same concept as the "scope" of an elaborated
* NOTE: This is not the same concept as the "scope" of an elaborated
* hierarchy. That is represented by NetScope objects after elaboration.
*/
@ -47,7 +50,43 @@ class LexicalScope {
// A virtual destructor is so that dynamic_cast can work.
virtual ~LexicalScope() { }
// Nets an variables (wires) in the scope
struct range_t {
// True if this is an exclude
bool exclude_flag;
// lower bound
// If low_open_flag is false and low_expr=0, then use -inf
bool low_open_flag;
PExpr*low_expr;
// upper bound
// If high_open_flag is false and high_expr=0, then use +inf
bool high_open_flag;
PExpr*high_expr;
// Next range description in list
struct range_t*next;
};
/* The scope has parameters that are evaluated when the scope
is elaborated. During parsing, I put the parameters into
this map. */
struct param_expr_t : public LineInfo {
param_expr_t() : type(IVL_VT_NO_TYPE), msb(0), lsb(0), signed_flag(false), expr(0), range(0) { }
// Type information
ivl_variable_type_t type;
PExpr*msb;
PExpr*lsb;
bool signed_flag;
// Value expression
PExpr*expr;
// If there are range constraints, list them here
range_t*range;
};
map<perm_string,param_expr_t>parameters;
map<perm_string,param_expr_t>localparams;
// Named events in the scope.
map<perm_string,PEvent*>events;
// Nets and variables (wires) in the scope
map<perm_string,PWire*>wires;
PWire* wires_find(perm_string name);
@ -55,6 +94,15 @@ class LexicalScope {
list<PProcess*> behaviors;
list<AProcess*> analog_behaviors;
protected:
void dump_parameters_(ostream&out, unsigned indent) const;
void dump_localparams_(ostream&out, unsigned indent) const;
void dump_events_(ostream&out, unsigned indent) const;
void dump_wires_(ostream&out, unsigned indent) const;
private:
};
@ -76,12 +124,7 @@ class PScope : public LexicalScope {
perm_string pscope_name() const { return name_; }
PScope* pscope_parent() { return parent_; }
// Named events in the scope.
map<perm_string,PEvent*>events;
protected:
void dump_wires_(ostream&out, unsigned indent) const;
bool elaborate_sig_wires_(Design*des, NetScope*scope) const;
bool elaborate_behaviors_(Design*des, NetScope*scope) const;

View File

@ -103,6 +103,8 @@ class PAssign_ : public Statement {
protected:
NetAssign_* elaborate_lval(Design*, NetScope*scope) const;
NetExpr* elaborate_rval_(Design*, NetScope*, unsigned lv_width,
ivl_variable_type_t type) const;
PExpr* delay_;
PEventStatement*event_;

View File

@ -35,16 +35,16 @@ typedef shl_t ivl_dll_t;
#endif
#if defined(__MINGW32__)
static inline ivl_dll_t ivl_dlopen(const char *name)
static __inline__ ivl_dll_t ivl_dlopen(const char *name)
{ return (void *)LoadLibrary(name); }
static inline void *ivl_dlsym(ivl_dll_t dll, const char *nm)
static __inline__ void *ivl_dlsym(ivl_dll_t dll, const char *nm)
{ return (void *)GetProcAddress((HINSTANCE)dll,nm);}
static inline void ivl_dlclose(ivl_dll_t dll)
static __inline__ void ivl_dlclose(ivl_dll_t dll)
{ (void)FreeLibrary((HINSTANCE)dll);}
static inline const char *dlerror(void)
static __inline__ const char *dlerror(void)
{
static char msg[256];
unsigned long err = GetLastError();
@ -61,10 +61,10 @@ static inline const char *dlerror(void)
}
#elif defined(HAVE_DLFCN_H)
static inline ivl_dll_t ivl_dlopen(const char*name)
static __inline__ ivl_dll_t ivl_dlopen(const char*name)
{ return dlopen(name,RTLD_LAZY); }
static inline void* ivl_dlsym(ivl_dll_t dll, const char*nm)
static __inline__ void* ivl_dlsym(ivl_dll_t dll, const char*nm)
{
void*sym = dlsym(dll, nm);
/* Not found? try without the leading _ */
@ -73,24 +73,24 @@ static inline void* ivl_dlsym(ivl_dll_t dll, const char*nm)
return sym;
}
static inline void ivl_dlclose(ivl_dll_t dll)
static __inline__ void ivl_dlclose(ivl_dll_t dll)
{ dlclose(dll); }
#elif defined(HAVE_DL_H)
static inline ivl_dll_t ivl_dlopen(const char*name)
static __inline__ ivl_dll_t ivl_dlopen(const char*name)
{ return shl_load(name, BIND_IMMEDIATE, 0); }
static inline void* ivl_dlsym(ivl_dll_t dll, const char*nm)
static __inline__ void* ivl_dlsym(ivl_dll_t dll, const char*nm)
{
void*sym;
int rc = shl_findsym(&dll, nm, TYPE_PROCEDURE, &sym);
return (rc == 0) ? sym : 0;
}
static inline void ivl_dlclose(ivl_dll_t dll)
static __inline__ void ivl_dlclose(ivl_dll_t dll)
{ shl_unload(dll); }
static inline const char*dlerror(void)
static __inline__ const char*dlerror(void)
{ return strerror( errno ); }
#endif

View File

@ -93,4 +93,4 @@
* junk, and support gcc 3.0. (Stephan Boettcher)
*
*/
#endif // __config_H
#endif /* __config_H */

View File

@ -124,4 +124,4 @@ AX_CPP_IDENT
# XXX disable tgt-fpga for the moment
AC_CONFIG_SUBDIRS(vvp vpi tgt-stub tgt-null tgt-vvp tgt-vhdl libveriuser cadpli)
AC_OUTPUT(Makefile ivlpp/Makefile driver/Makefile driver-vpi/Makefile tgt-null/Makefile tgt-verilog/Makefile tgt-pal/Makefile tgt-vhdl/Makefile)
AC_OUTPUT(Makefile ivlpp/Makefile driver/Makefile driver-vpi/Makefile tgt-null/Makefile tgt-verilog/Makefile tgt-pal/Makefile)

View File

@ -241,11 +241,14 @@ void NetNode::dump_node(ostream&o, unsigned ind) const
/* This is the generic dumping of all the signals connected to each
pin of the object. The "this" object is not printed, only the
signals connected to this. */
void NetPins::dump_node_pins(ostream&o, unsigned ind) const
void NetPins::dump_node_pins(ostream&o, unsigned ind, const char**pin_names) const
{
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
o << setw(ind) << "" << idx << " " << pin(idx).get_name()
<< "<" << pin(idx).get_inst() << ">";
o << setw(ind) << "" << idx;
if (pin_names && pin_names[idx])
o << " " << pin_names[idx];
else
o << " pin" << idx;
switch (pin(idx).get_dir()) {
case Link::PASSIVE:
@ -294,7 +297,14 @@ void NetAddSub::dump_node(ostream&o, unsigned ind) const
o << setw(ind) << "" << "Adder (NetAddSub): " << name()
<< " width=" << width() << " pin_count=" << pin_count()
<< endl;
dump_node_pins(o, ind+4);
static const char* pin_names[] = {
"Cout ",
"DataA ",
"DataB ",
"Result"
};
dump_node_pins(o, ind+4, pin_names);
dump_obj_attr(o, ind+4);
}
@ -567,8 +577,14 @@ void NetReplicate::dump_node(ostream&o, unsigned ind) const
void NetSignExtend::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "NetSignExtend: "
<< name() << " output width=" << width_ << endl;
o << setw(ind) << "" << "NetSignExtend: " << name();
if (rise_time())
o << " #(" << *rise_time()
<< "," << *fall_time()
<< "," << *decay_time() << ")";
else
o << " #(.,.,.)";
o << " output width=" << width_ << endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
}
@ -702,6 +718,11 @@ void NetProcTop::dump(ostream&o, unsigned ind) const
statement_->dump(o, ind+2);
}
void NetAlloc::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "// allocate storage : " << scope_path(scope_) << endl;
}
void NetAssign_::dump_lval(ostream&o) const
{
if (sig_) {
@ -753,6 +774,11 @@ void NetAssignNB::dump(ostream&o, unsigned ind) const
if (const NetExpr*de = get_delay())
o << "#(" << *de << ") ";
if (count_)
o << "repeat(" << *count_ << ") ";
if (event_) {
o << *event_;
}
o << *rval() << ";" << endl;
@ -897,6 +923,25 @@ void NetEvWait::dump(ostream&o, unsigned ind) const
o << setw(ind+2) << "" << "/* noop */ ;" << endl;
}
ostream& operator << (ostream&out, const NetEvWait&obj)
{
obj.dump_inline(out);
return out;
}
void NetEvWait::dump_inline(ostream&o) const
{
o << "@(";
if (nevents() > 0)
o << event(0)->name();
for (unsigned idx = 1 ; idx < nevents() ; idx += 1)
o << " or " << event(idx)->name();
o << ") ";
}
void NetForce::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "force ";
@ -910,6 +955,11 @@ void NetForever::dump(ostream&o, unsigned ind) const
statement_->dump(o, ind+2);
}
void NetFree::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "// free storage : " << scope_path(scope_) << endl;
}
void NetFuncDef::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "function definition for " << scope_path(scope_) << endl;

View File

@ -51,6 +51,7 @@ const char HELP[] =
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include <sys/types.h>
@ -259,18 +260,104 @@ static const char*my_tempfile(const char*str, FILE**fout)
return pathbuf;
}
static int t_version_only(void)
{
remove(source_path);
fflush(0);
snprintf(tmp, sizeof tmp, "%s%civlpp -V", pbase, sep);
system(tmp);
fflush(0);
snprintf(tmp, sizeof tmp, "%s%civl -V -C%s -C%s", pbase, sep,
iconfig_path, iconfig_common_path);
system(tmp);
if ( ! getenv("IVERILOG_ICONFIG")) {
remove(iconfig_path);
remove(defines_path);
remove(compiled_defines_path);
}
return 0;
}
static void build_preprocess_command(int e_flag)
{
snprintf(tmp, sizeof tmp, "%s%civlpp %s%s -F%s -f%s -p%s ",
pbase,sep, verbose_flag?" -v":"",
e_flag?"":" -L", defines_path, source_path,
compiled_defines_path);
}
static int t_preprocess_only(void)
{
int rc;
char*cmd;
unsigned ncmd;
build_preprocess_command(1);
ncmd = strlen(tmp);
cmd = malloc(ncmd+1);
strcpy(cmd, tmp);
if (strcmp(opath,"-") != 0) {
snprintf(tmp, sizeof tmp, " > %s", opath);
cmd = realloc(cmd, ncmd+strlen(tmp)+1);
strcpy(cmd+ncmd, tmp);
ncmd += strlen(tmp);
}
if (verbose_flag)
printf("preprocess: %s\n", cmd);
rc = system(cmd);
remove(source_path);
if ( ! getenv("IVERILOG_ICONFIG")) {
remove(iconfig_path);
remove(defines_path);
remove(compiled_defines_path);
}
if (rc != 0) {
if (WIFEXITED(rc)) {
fprintf(stderr, "errors preprocessing Verilog program.\n");
return WEXITSTATUS(rc);
}
fprintf(stderr, "Command signaled: %s\n", cmd);
free(cmd);
return -1;
}
return 0;
}
/*
* This is the default target type. It looks up the bits that are
* needed to run the command from the configuration file (which is
* already parsed for us) so we can handle must of the generic cases.
*/
static int t_default(char*cmd, unsigned ncmd)
static int t_compile()
{
unsigned rc;
/* Start by building the preprocess command line. */
build_preprocess_command(0);
size_t ncmd = strlen(tmp);
char*cmd = malloc(ncmd + 1);
strcpy(cmd, tmp);
#ifdef __MINGW32__
unsigned ncmd_start = ncmd;
#else
int rtn;
#endif
/* Build the ivl command and pipe it to the preprocessor. */
snprintf(tmp, sizeof tmp, " | %s/ivl", base);
rc = strlen(tmp);
cmd = realloc(cmd, ncmd+rc+1);
@ -331,7 +418,7 @@ static int t_default(char*cmd, unsigned ncmd)
free(cmd);
return rc;
#else
int rtn = 0;
rtn = 0;
if (rc != 0) {
if (rc == 127) {
fprintf(stderr, "Failed to execute: %s\n", cmd);
@ -533,8 +620,6 @@ void add_sft_file(const char *module)
int main(int argc, char **argv)
{
char*cmd;
unsigned ncmd;
int e_flag = 0;
int version_flag = 0;
int opt, idx, rc;
@ -748,9 +833,6 @@ int main(int argc, char **argv)
printf("Icarus Verilog version " VERSION " (" VERSION_TAG ")\n\n");
printf("Copyright 1998-2008 Stephen Williams\n");
puts(NOTICE);
if (version_flag)
return 0;
}
/* Make a common conf file path to reflect the target. */
@ -833,61 +915,11 @@ int main(int argc, char **argv)
fclose(defines_file);
defines_file = 0;
if (source_count == 0) {
if (source_count == 0 && !version_flag) {
fprintf(stderr, "%s: no source files.\n\n%s\n", argv[0], HELP);
return 1;
}
/* Start building the preprocess command line. */
sprintf(tmp, "%s%civlpp %s%s -F%s -f%s -p%s ", pbase,sep,
verbose_flag?" -v":"",
e_flag?"":" -L", defines_path, source_path,
compiled_defines_path);
ncmd = strlen(tmp);
cmd = malloc(ncmd + 1);
strcpy(cmd, tmp);
/* If the -E flag was given on the command line, then all we
do is run the preprocessor and put the output where the
user wants it. */
if (e_flag) {
int rc;
if (strcmp(opath,"-") != 0) {
sprintf(tmp, " > %s", opath);
cmd = realloc(cmd, ncmd+strlen(tmp)+1);
strcpy(cmd+ncmd, tmp);
ncmd += strlen(tmp);
}
if (verbose_flag)
printf("preprocess: %s\n", cmd);
rc = system(cmd);
remove(source_path);
fclose(iconfig_file);
if ( ! getenv("IVERILOG_ICONFIG")) {
remove(iconfig_path);
remove(defines_path);
remove(compiled_defines_path);
}
if (rc != 0) {
if (WIFEXITED(rc)) {
fprintf(stderr, "errors preprocessing Verilog program.\n");
return WEXITSTATUS(rc);
}
fprintf(stderr, "Command signaled: %s\n", cmd);
free(cmd);
return -1;
}
return 0;
}
fprintf(iconfig_file, "iwidth:%u\n", integer_width);
/* Write the preprocessor command needed to preprocess a
@ -899,5 +931,16 @@ int main(int argc, char **argv)
/* Done writing to the iconfig file. Close it now. */
fclose(iconfig_file);
return t_default(cmd, ncmd);
/* If we're only here for the version output, then we're done. */
if (version_flag)
return t_version_only();
/* If the -E flag was given on the command line, then all we
do is run the preprocessor and put the output where the
user wants it. */
if (e_flag)
return t_preprocess_only();
/* Otherwise, this is a full compile. */
return t_compile();
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -268,66 +268,57 @@ NetExpr*PEUnary::elaborate_pexpr (Design*des, NetScope*scope) const
return tmp;
}
/* Reuse these routines from eval_tree.cc. */
NetExpr* evaluate_clog2(NetExpr*arg);
NetExpr* evaluate_math_one_arg(NetExpr*arg, const char*name);
NetExpr* evaluate_math_two_args(NetExpr*arg0, NetExpr*arg1, const char*name);
NetExpr* evaluate_abs(NetExpr*arg);
NetExpr* evaluate_min_max(NetExpr*arg0, NetExpr*arg1, const char*name);
NetExpr* PECallFunction::elaborate_pexpr(Design*des, NetScope*scope) const
{
/* Only $clog2 and the builtin mathematical functions can
* be a constant system function. */
perm_string name = peek_tail_name(path_);
if (name[0] == '$' && (generation_flag >= GN_VER2005 ||
gn_icarus_misc_flag || gn_verilog_ams_flag)) {
if (name == "$clog2" ||
name == "$ln" ||
name == "$log10" ||
name == "$exp" ||
name == "$sqrt" ||
name == "$floor" ||
name == "$ceil" ||
name == "$sin" ||
name == "$cos" ||
name == "$tan" ||
name == "$asin" ||
name == "$acos" ||
name == "$atan" ||
name == "$sinh" ||
name == "$cosh" ||
name == "$tanh" ||
name == "$asinh" ||
name == "$acosh" ||
name == "$atanh") {
perm_string nm = peek_tail_name(path_);
if (nm[0] == '$' && (generation_flag >= GN_VER2005 ||
gn_icarus_misc_flag || gn_verilog_ams_flag)) {
if (nm == "$clog2" ||
nm == "$ln" ||
nm == "$log10" ||
nm == "$exp" ||
nm == "$sqrt" ||
nm == "$floor" ||
nm == "$ceil" ||
nm == "$sin" ||
nm == "$cos" ||
nm == "$tan" ||
nm == "$asin" ||
nm == "$acos" ||
nm == "$atan" ||
nm == "$sinh" ||
nm == "$cosh" ||
nm == "$tanh" ||
nm == "$asinh" ||
nm == "$acosh" ||
nm == "$atanh") {
if (parms_.size() != 1 || parms_[0] == 0) {
cerr << get_fileline() << ": error: " << name
cerr << get_fileline() << ": error: " << nm
<< " takes a single argument." << endl;
des->errors += 1;
return 0;
}
NetExpr*arg = parms_[0]->elaborate_pexpr(des, scope);
if (arg == 0) return 0;
eval_expr(arg);
NetExpr*rtn;
if (peek_tail_name(path_) == "$clog2") {
rtn = evaluate_clog2(arg);
NetESFunc*rtn;
if (nm == "$clog2") {
rtn = new NetESFunc(nm, IVL_VT_BOOL, integer_width, 1);
} else {
rtn = evaluate_math_one_arg(arg, name.str());
}
delete arg;
if (rtn != 0) {
rtn->set_line(*this);
return rtn;
rtn = new NetESFunc(nm, IVL_VT_REAL, 1, 1);
}
rtn->set_line(*this);
rtn->cast_signed(true);
rtn->parm(0, arg);
return rtn;
}
if (name == "$pow" ||
name == "$atan2" ||
name == "$hypot") {
if (nm == "$pow" ||
nm == "$atan2" ||
nm == "$hypot") {
if (parms_.size() != 2 || parms_[0] == 0 || parms_[1] == 0) {
cerr << get_fileline() << ": error: " << name
cerr << get_fileline() << ": error: " << nm
<< " takes two arguments." << endl;
des->errors += 1;
return 0;
@ -335,45 +326,44 @@ NetExpr* PECallFunction::elaborate_pexpr(Design*des, NetScope*scope) const
NetExpr*arg0 = parms_[0]->elaborate_pexpr(des, scope);
NetExpr*arg1 = parms_[1]->elaborate_pexpr(des, scope);
if (arg0 == 0 || arg1 == 0) return 0;
eval_expr(arg0);
eval_expr(arg1);
NetExpr*rtn = evaluate_math_two_args(arg0, arg1, name.str());
delete arg0;
delete arg1;
if (rtn != 0) {
rtn->set_line(*this);
return rtn;
}
NetESFunc*rtn = new NetESFunc(nm, IVL_VT_REAL, 1, 2);
rtn->set_line(*this);
rtn->cast_signed(true);
rtn->parm(0, arg0);
rtn->parm(1, arg1);
return rtn;
}
/* These are only available with verilog-ams or icarus-misc. */
if ((gn_icarus_misc_flag || gn_verilog_ams_flag) &&
(name == "$log" || name == "$abs")) {
(nm == "$log" || nm == "$abs")) {
if (parms_.size() != 1 || parms_[0] == 0) {
cerr << get_fileline() << ": error: " << name
cerr << get_fileline() << ": error: " << nm
<< " takes a single argument." << endl;
des->errors += 1;
return 0;
}
NetExpr*arg = parms_[0]->elaborate_pexpr(des, scope);
if (arg == 0) return 0;
eval_expr(arg);
NetExpr*rtn;
if (peek_tail_name(path_) == "$log") {
rtn = evaluate_math_one_arg(arg, name.str());
NetESFunc*rtn;
if (nm == "$log") {
rtn = new NetESFunc(nm, IVL_VT_REAL, 1, 1);
} else {
rtn = evaluate_abs(arg);
}
delete arg;
if (rtn != 0) {
rtn->set_line(*this);
return rtn;
/* This can return either a real or an arbitrary
* width vector, so set things to fail if this
* does not get replaced with a constant during
* elaboration. */
rtn = new NetESFunc(nm, IVL_VT_NO_TYPE, 0, 1);
}
rtn->set_line(*this);
rtn->cast_signed(true);
rtn->parm(0, arg);
return rtn;
}
if ((gn_icarus_misc_flag || gn_verilog_ams_flag) &&
(name == "$min" || name == "$max")) {
(nm == "$min" || nm == "$max")) {
if (parms_.size() != 2 || parms_[0] == 0 || parms_[1] == 0) {
cerr << get_fileline() << ": error: " << name
cerr << get_fileline() << ": error: " << nm
<< " takes two arguments." << endl;
des->errors += 1;
return 0;
@ -381,15 +371,13 @@ NetExpr* PECallFunction::elaborate_pexpr(Design*des, NetScope*scope) const
NetExpr*arg0 = parms_[0]->elaborate_pexpr(des, scope);
NetExpr*arg1 = parms_[1]->elaborate_pexpr(des, scope);
if (arg0 == 0 || arg1 == 0) return 0;
eval_expr(arg0);
eval_expr(arg1);
NetExpr*rtn = evaluate_min_max(arg0, arg1, name.str());
delete arg0;
delete arg1;
if (rtn != 0) {
rtn->set_line(*this);
return rtn;
}
/* See $log above for why this has no type or width. */
NetESFunc*rtn = new NetESFunc(nm, IVL_VT_NO_TYPE, 0, 2);
rtn->set_line(*this);
rtn->cast_signed(true);
rtn->parm(0, arg0);
rtn->parm(1, arg1);
return rtn;
}
cerr << get_fileline() << ": error: this is not a constant "

View File

@ -46,8 +46,42 @@
# include <assert.h>
# include "ivl_assert.h"
void Module::elaborate_parm_item_(perm_string name, const param_expr_t&cur,
Design*des, NetScope*scope)
typedef map<perm_string,LexicalScope::param_expr_t>::const_iterator mparm_it_t;
static void collect_scope_parameters_(NetScope*scope,
const map<perm_string,LexicalScope::param_expr_t>&parameters)
{
for (mparm_it_t cur = parameters.begin()
; cur != parameters.end() ; cur ++) {
NetEParam*tmp = new NetEParam;
tmp->set_line(*((*cur).second.expr));
tmp->cast_signed( (*cur).second.signed_flag );
scope->set_parameter((*cur).first, tmp, (*cur).second.type,
0, 0, false, 0, (*cur).second);
}
}
static void collect_scope_localparams_(NetScope*scope,
const map<perm_string,LexicalScope::param_expr_t>&localparams)
{
for (mparm_it_t cur = localparams.begin()
; cur != localparams.end() ; cur ++) {
NetEParam*tmp = new NetEParam;
tmp->set_line(*((*cur).second.expr));
if ((*cur).second.msb)
tmp->cast_signed( (*cur).second.signed_flag );
scope->set_parameter((*cur).first, tmp, (*cur).second.type,
0, 0, false, 0, (*cur).second);
}
}
static void elaborate_parm_item_(perm_string name,
const LexicalScope::param_expr_t&cur,
Design*des, NetScope*scope)
{
PExpr*ex = cur.expr;
assert(ex);
@ -72,7 +106,7 @@ void Module::elaborate_parm_item_(perm_string name, const param_expr_t&cur,
}
NetScope::range_t*range_list = 0;
for (Module::range_t*range = cur.range ; range ; range = range->next) {
for (LexicalScope::range_t*range = cur.range ; range ; range = range->next) {
NetScope::range_t*tmp = new NetScope::range_t;
tmp->exclude_flag = range->exclude_flag;
tmp->low_open_flag = range->low_open_flag;
@ -131,6 +165,66 @@ void Module::elaborate_parm_item_(perm_string name, const param_expr_t&cur,
delete val;
}
static void elaborate_scope_parameters_(Design*des, NetScope*scope,
const map<perm_string,LexicalScope::param_expr_t>&parameters)
{
for (mparm_it_t cur = parameters.begin()
; cur != parameters.end() ; cur ++) {
elaborate_parm_item_((*cur).first, (*cur).second, des, scope);
}
}
static void elaborate_scope_localparams_(Design*des, NetScope*scope,
const map<perm_string,LexicalScope::param_expr_t>&localparams)
{
for (mparm_it_t cur = localparams.begin()
; cur != localparams.end() ; cur ++) {
elaborate_parm_item_((*cur).first, (*cur).second, des, scope);
}
}
static void replace_scope_parameters_(NetScope*scope, const LineInfo&loc,
const Module::replace_t&replacements)
{
for (Module::replace_t::const_iterator cur = replacements.begin()
; cur != replacements.end() ; cur ++) {
NetExpr*val = (*cur).second;
if (val == 0) {
cerr << loc.get_fileline() << ": internal error: "
<< "Missing expression in parameter replacement for "
<< (*cur).first;
}
assert(val);
if (debug_scopes) {
cerr << loc.get_fileline() << ": debug: "
<< "Replace " << (*cur).first
<< " with expression " << *val
<< " from " << val->get_fileline() << "." << endl;
cerr << loc.get_fileline() << ": : "
<< "Type=" << val->expr_type() << endl;
}
bool flag = scope->replace_parameter((*cur).first, val);
if (! flag) {
cerr << val->get_fileline() << ": warning: parameter "
<< (*cur).first << " not found in "
<< scope_path(scope) << "." << endl;
}
}
}
static void elaborate_scope_events_(Design*des, NetScope*scope,
const map<perm_string,PEvent*>&events)
{
for (map<perm_string,PEvent*>::const_iterator et = events.begin()
; et != events.end() ; et ++ ) {
(*et).second->elaborate_scope(des, scope);
}
}
static void elaborate_scope_tasks(Design*des, NetScope*scope,
const LineInfo&loc,
const map<perm_string,PTask*>&tasks)
@ -242,79 +336,25 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
// the pform and just place a NetEParam placeholder in the
// place of the elaborated expression.
typedef map<perm_string,param_expr_t>::const_iterator mparm_it_t;
// Scan the parameters in the module, and create stub parameter
// entries in the scope for the parameter names.
// This loop scans the parameters in the module, and creates
// stub parameter entries in the scope for the parameter name.
for (mparm_it_t cur = parameters.begin()
; cur != parameters.end() ; cur ++) {
NetEParam*tmp = new NetEParam;
tmp->set_line(*((*cur).second.expr));
tmp->cast_signed( (*cur).second.signed_flag );
scope->set_parameter((*cur).first, tmp, (*cur).second.type,
0, 0, false, 0, (*cur).second);
}
for (mparm_it_t cur = localparams.begin()
; cur != localparams.end() ; cur ++) {
NetEParam*tmp = new NetEParam;
tmp->set_line(*((*cur).second.expr));
if ((*cur).second.msb)
tmp->cast_signed( (*cur).second.signed_flag );
scope->set_parameter((*cur).first, tmp, (*cur).second.type,
0, 0, false, 0, (*cur).second);
}
collect_scope_parameters_(scope, parameters);
collect_scope_localparams_(scope, localparams);
// Now scan the parameters again, this time elaborating them
// for use as parameter values. This is after the previous
// scan so that local parameter names can be used in the
// r-value expressions.
for (mparm_it_t cur = parameters.begin()
; cur != parameters.end() ; cur ++) {
elaborate_parm_item_((*cur).first, (*cur).second, des, scope);
}
elaborate_scope_parameters_(des, scope, parameters);
/* run parameter replacements that were collected from the
containing scope and meant for me. */
for (replace_t::const_iterator cur = replacements.begin()
; cur != replacements.end() ; cur ++) {
replace_scope_parameters_(scope, *this, replacements);
NetExpr*val = (*cur).second;
if (val == 0) {
cerr << get_fileline() << ": internal error: "
<< "Missing expression in parameter replacement for "
<< (*cur).first;
}
assert(val);
if (debug_scopes) {
cerr << get_fileline() << ": debug: "
<< "Replace " << (*cur).first
<< " with expression " << *val
<< " from " << val->get_fileline() << "." << endl;
cerr << get_fileline() << ": : "
<< "Type=" << val->expr_type() << endl;
}
bool flag = scope->replace_parameter((*cur).first, val);
if (! flag) {
cerr << val->get_fileline() << ": warning: parameter "
<< (*cur).first << " not found in "
<< scope_path(scope) << "." << endl;
}
}
for (mparm_it_t cur = localparams.begin()
; cur != localparams.end() ; cur ++) {
elaborate_parm_item_((*cur).first, (*cur).second, des, scope);
}
elaborate_scope_localparams_(des, scope, localparams);
// Run through the defparams for this module, elaborate the
// expressions in this context and save the result is a table
@ -401,11 +441,7 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
// elaboration, so do it now. This allows for normal
// elaboration to reference these events.
for (map<perm_string,PEvent*>::const_iterator et = events.begin()
; et != events.end() ; et ++ ) {
(*et).second->elaborate_scope(des, scope);
}
elaborate_scope_events_(des, scope, events);
return des->errors == 0;
}
@ -693,6 +729,16 @@ void PGenerate::elaborate_subscope_(Design*des, NetScope*scope)
(*cur) -> generate_scope(des, scope);
}
// Scan the localparams in this scope, and create stub parameter
// entries in the scope for the parameter names.
collect_scope_localparams_(scope, localparams);
// Now scan the localparams again, this time elaborating them
// for use as parameter values.
elaborate_scope_localparams_(des, scope, localparams);
// Scan through all the task and function declarations in this
// scope.
elaborate_scope_tasks(des, scope, *this, tasks);
elaborate_scope_funcs(des, scope, *this, funcs);
@ -710,6 +756,9 @@ void PGenerate::elaborate_subscope_(Design*des, NetScope*scope)
(*cur) -> statement() -> elaborate_scope(des, scope);
}
// Scan through all the named events in this scope.
elaborate_scope_events_(des, scope, events);
// Save the scope that we created, for future use.
scope_list_.push_back(scope);
}
@ -991,6 +1040,25 @@ void PFunction::elaborate_scope(Design*des, NetScope*scope) const
{
assert(scope->type() == NetScope::FUNC);
// Scan the parameters in the function, and create stub parameter
// entries in the scope for the parameter names.
collect_scope_parameters_(scope, parameters);
collect_scope_localparams_(scope, localparams);
// Now scan the parameters again, this time elaborating them
// for use as parameter values. This is after the previous
// scan so that local parameter names can be used in the
// r-value expressions.
elaborate_scope_parameters_(des, scope, parameters);
elaborate_scope_localparams_(des, scope, localparams);
// Scan through all the named events in this scope.
elaborate_scope_events_(des, scope, events);
if (statement_)
statement_->elaborate_scope(des, scope);
}
@ -999,6 +1067,25 @@ void PTask::elaborate_scope(Design*des, NetScope*scope) const
{
assert(scope->type() == NetScope::TASK);
// Scan the parameters in the task, and create stub parameter
// entries in the scope for the parameter names.
collect_scope_parameters_(scope, parameters);
collect_scope_localparams_(scope, localparams);
// Now scan the parameters again, this time elaborating them
// for use as parameter values. This is after the previous
// scan so that local parameter names can be used in the
// r-value expressions.
elaborate_scope_parameters_(des, scope, parameters);
elaborate_scope_localparams_(des, scope, localparams);
// Scan through all the named events in this scope.
elaborate_scope_events_(des, scope, events);
if (statement_)
statement_->elaborate_scope(des, scope);
}
@ -1035,11 +1122,29 @@ void PBlock::elaborate_scope(Design*des, NetScope*scope) const
? NetScope::FORK_JOIN
: NetScope::BEGIN_END);
my_scope->set_line(get_file(), get_lineno());
// Scan the parameters in the module, and create stub parameter
// entries in the scope for the parameter names.
collect_scope_parameters_(my_scope, parameters);
collect_scope_localparams_(my_scope, localparams);
// Now scan the parameters again, this time elaborating them
// for use as parameter values. This is after the previous
// scan so that local parameter names can be used in the
// r-value expressions.
elaborate_scope_parameters_(des, my_scope, parameters);
elaborate_scope_localparams_(des, my_scope, localparams);
// Scan through all the named events in this scope.
elaborate_scope_events_(des, my_scope, events);
}
for (unsigned idx = 0 ; idx < list_.count() ; idx += 1)
list_[idx] -> elaborate_scope(des, my_scope);
}
/*

File diff suppressed because it is too large Load Diff

26
emit.cc
View File

@ -196,6 +196,12 @@ bool NetProc::emit_proc(struct target_t*tgt) const
return false;
}
bool NetAlloc::emit_proc(struct target_t*tgt) const
{
tgt->proc_alloc(this);
return true;
}
bool NetAssign::emit_proc(struct target_t*tgt) const
{
return tgt->proc_assign(this);
@ -249,6 +255,12 @@ bool NetForever::emit_proc(struct target_t*tgt) const
return true;
}
bool NetFree::emit_proc(struct target_t*tgt) const
{
tgt->proc_free(this);
return true;
}
bool NetPDelay::emit_proc(struct target_t*tgt) const
{
return tgt->proc_delay(this);
@ -540,17 +552,3 @@ void NetEUnary::expr_scan(struct expr_scan_t*tgt) const
{
tgt->expr_unary(this);
}
int emit(const Design*des, const char*type)
{
for (unsigned idx = 0 ; target_table[idx] ; idx += 1) {
const struct target*tgt = target_table[idx];
if (strcmp(tgt->name, type) == 0)
return des->emit(tgt->meth);
}
cerr << "error: Code generator type " << type
<< " not found." << endl;
return -1;
}

View File

@ -133,6 +133,8 @@ NetExpr* NetEBAdd::eval_tree(int prune_to_width)
verinum lval = lc->value();
verinum rval = rc->value();
ivl_assert(*this, se->expr_width() == this->expr_width());
verinum val;
if (op_ == se->op_) {
/* (a + lval) + rval --> a + (rval+lval) */
@ -144,6 +146,13 @@ NetExpr* NetEBAdd::eval_tree(int prune_to_width)
val = rval - lval;
}
val = pad_to_width(val, expr_width());
if (val.len() > expr_width()) {
verinum tmp (val, expr_width());
tmp.has_sign(val.has_sign());
val = tmp;
}
NetEConst*tmp = new NetEConst(val);
left_ = se->left_->dup_expr();
delete se;
@ -528,6 +537,13 @@ NetEConst* NetEBComp::eval_gteq_()
}
}
/*
* Evaluate <A>==<B> or <A>!=<B>. The equality operator checks all the
* bits and returns true(false) if there are any bits in the vector
* that are defined (0 or 1) and different. If all the defined bits
* are equal, but there are are x/z bits, then the situation is
* ambiguous so the result is x.
*/
NetEConst* NetEBComp::eval_eqeq_real_(NetExpr*le, NetExpr*ri, bool ne_flag)
{
NetEConst*vtmp;
@ -606,11 +622,14 @@ NetEConst* NetEBComp::eval_eqeq_(bool ne_flag)
for (unsigned idx = 0 ; idx < top ; idx += 1) {
bool x_bit_present = false;
switch (lv.get(idx)) {
case verinum::Vx:
case verinum::Vz:
res = verinum::Vx;
x_bit_present = true;
break;
default:
@ -622,17 +641,20 @@ NetEConst* NetEBComp::eval_eqeq_(bool ne_flag)
case verinum::Vx:
case verinum::Vz:
res = verinum::Vx;
x_bit_present = true;
break;
default:
break;
}
if (res == verinum::Vx)
break;
if (x_bit_present)
continue;
if (rv.get(idx) != lv.get(idx))
if (rv.get(idx) != lv.get(idx)) {
res = ne_res;
break;
}
}
if (res != verinum::Vx) {
@ -1633,8 +1655,9 @@ NetEConst* NetEUReduce::eval_tree(int prune_to_width)
return new NetEConst(verinum(res, 1));
}
NetExpr* evaluate_clog2(NetExpr*arg)
NetExpr* evaluate_clog2(NetExpr*&arg)
{
eval_expr(arg);
NetEConst*tmpi = dynamic_cast<NetEConst *>(arg);
NetECReal*tmpr = dynamic_cast<NetECReal *>(arg);
if (tmpi || tmpr) {
@ -1645,9 +1668,9 @@ NetExpr* evaluate_clog2(NetExpr*arg)
arg = verinum(tmpr->value().as_double(), true);
}
/* If we have an x in the verinum we return 32'bx. */
/* If we have an x in the verinum we return 'bx. */
if (!arg.is_defined()) {
verinum tmp (verinum::Vx, 32);
verinum tmp (verinum::Vx, integer_width);
tmp.has_sign(true);
NetEConst*rtn = new NetEConst(tmp);
return rtn;
@ -1675,7 +1698,7 @@ NetExpr* evaluate_clog2(NetExpr*arg)
if (is_neg && res < integer_width)
res = integer_width;
verinum tmp (res, 32);
verinum tmp (res, integer_width);
NetEConst*rtn = new NetEConst(tmp);
return rtn;
}
@ -1683,8 +1706,9 @@ NetExpr* evaluate_clog2(NetExpr*arg)
return 0;
}
NetExpr* evaluate_math_one_arg(NetExpr*arg, const char*name)
NetExpr* evaluate_math_one_arg(NetExpr*&arg, const char*name)
{
eval_expr(arg);
NetEConst*tmpi = dynamic_cast<NetEConst *>(arg);
NetECReal*tmpr = dynamic_cast<NetECReal *>(arg);
if (tmpi || tmpr) {
@ -1739,8 +1763,10 @@ NetExpr* evaluate_math_one_arg(NetExpr*arg, const char*name)
return 0;
}
NetExpr* evaluate_math_two_args(NetExpr*arg0, NetExpr*arg1, const char*name)
NetExpr* evaluate_math_two_args(NetExpr*&arg0, NetExpr*&arg1, const char*name)
{
eval_expr(arg0);
eval_expr(arg1);
NetEConst*tmpi0 = dynamic_cast<NetEConst *>(arg0);
NetECReal*tmpr0 = dynamic_cast<NetECReal *>(arg0);
NetEConst*tmpi1 = dynamic_cast<NetEConst *>(arg1);
@ -1770,8 +1796,9 @@ NetExpr* evaluate_math_two_args(NetExpr*arg0, NetExpr*arg1, const char*name)
return 0;
}
NetExpr* evaluate_abs(NetExpr*arg)
NetExpr* evaluate_abs(NetExpr*&arg)
{
eval_expr(arg);
NetEConst*tmpi = dynamic_cast<NetEConst *>(arg);
if (tmpi) {
verinum arg = tmpi->value();
@ -1790,8 +1817,10 @@ NetExpr* evaluate_abs(NetExpr*arg)
return 0;
}
NetExpr* evaluate_min_max(NetExpr*arg0, NetExpr*arg1, const char*name)
NetExpr* evaluate_min_max(NetExpr*&arg0, NetExpr*&arg1, const char*name)
{
eval_expr(arg0);
eval_expr(arg1);
NetEConst*tmpi0 = dynamic_cast<NetEConst *>(arg0);
NetECReal*tmpr0 = dynamic_cast<NetECReal *>(arg0);
NetEConst*tmpi1 = dynamic_cast<NetEConst *>(arg1);
@ -1866,11 +1895,13 @@ NetExpr* NetESFunc::eval_tree(int prune_to_width)
<< " takes a single argument." << endl;
return 0;
}
NetExpr*arg = parm(0)->dup_expr();
if (strcmp(nm, "$clog2") == 0) {
rtn = evaluate_clog2(parm(0));
rtn = evaluate_clog2(arg);
} else {
rtn = evaluate_math_one_arg(parm(0), nm);
rtn = evaluate_math_one_arg(arg, nm);
}
delete arg;
}
if (strcmp(nm, "$pow") == 0 ||
@ -1881,7 +1912,11 @@ NetExpr* NetESFunc::eval_tree(int prune_to_width)
<< " takes two arguments." << endl;
return 0;
}
rtn = evaluate_math_two_args(parm(0), parm(1), nm);
NetExpr*arg0 = parm(0)->dup_expr();
NetExpr*arg1 = parm(1)->dup_expr();
rtn = evaluate_math_two_args(arg0, arg1, nm);
delete arg0;
delete arg1;
}
if ((gn_icarus_misc_flag || gn_verilog_ams_flag) &&
@ -1891,11 +1926,13 @@ NetExpr* NetESFunc::eval_tree(int prune_to_width)
<< " takes a single argument." << endl;
return 0;
}
NetExpr*arg = parm(0)->dup_expr();
if (strcmp(nm, "$log") == 0) {
rtn = evaluate_math_one_arg(parm(0), nm);
rtn = evaluate_math_one_arg(arg, nm);
} else {
rtn = evaluate_abs(parm(0));
rtn = evaluate_abs(arg);
}
delete arg;
}
if ((gn_icarus_misc_flag || gn_verilog_ams_flag) &&
@ -1905,7 +1942,11 @@ NetExpr* NetESFunc::eval_tree(int prune_to_width)
<< " takes two arguments." << endl;
return 0;
}
rtn = evaluate_min_max(parm(0), parm(1), nm);
NetExpr*arg0 = parm(0)->dup_expr();
NetExpr*arg1 = parm(1)->dup_expr();
rtn = evaluate_min_max(arg0, arg1, nm);
delete arg0;
delete arg1;
}
if (rtn != 0) {

View File

@ -20,56 +20,56 @@
# include "config.h"
# include "compiler.h"
# include <cstdlib>
# include <iostream>
# include "netlist.h"
# include "netmisc.h"
# include "ivl_assert.h"
NetNet* convert_to_real_const(Design*des, NetExpr*expr, NetExpr*obj)
static NetNet* convert_to_real_const(Design*des, NetScope*scope, NetEConst*expr)
{
NetNet* sig;
if (NetEConst*tmp = dynamic_cast<NetEConst*>(expr)) {
verireal vrl(tmp->value().as_double());
NetECReal rlval(vrl);
sig = rlval.synthesize(des);
} else {
cerr << obj->get_fileline() << ": sorry: Cannot convert "
"bit based value (" << *expr << ") to real." << endl;
des->errors += 1;
sig = 0;
}
verireal vrl(expr->value().as_double());
NetECReal rlval(vrl);
NetNet* sig = rlval.synthesize(des, scope);
return sig;
}
/* Note that lsig, rsig and real_args are references. */
bool process_binary_args(Design*des, NetExpr*left, NetExpr*right,
NetNet*&lsig, NetNet*&rsig, bool&real_args,
NetExpr*obj)
static bool process_binary_args(Design*des, NetScope*scope,
NetExpr*left, NetExpr*right,
NetNet*&lsig, NetNet*&rsig, bool&real_args,
NetExpr*obj)
{
if (left->expr_type() == IVL_VT_REAL ||
right->expr_type() == IVL_VT_REAL) {
real_args = true;
/* Currently we will have a runtime assert if both expressions
are not real, though we can convert constants. */
/* Convert the arguments to real. Handle the special
cases of constants, which can be converted more directly. */
if (left->expr_type() == IVL_VT_REAL) {
lsig = left->synthesize(des);
lsig = left->synthesize(des, scope);
} else if (NetEConst*tmp = dynamic_cast<NetEConst*> (left)) {
lsig = convert_to_real_const(des, scope, tmp);
} else {
lsig = convert_to_real_const(des, left, obj);
NetNet*tmp = left->synthesize(des, scope);
lsig = cast_to_real(des, scope, tmp);
}
if (right->expr_type() == IVL_VT_REAL) {
rsig = right->synthesize(des);
rsig = right->synthesize(des, scope);
} else if (NetEConst*tmp = dynamic_cast<NetEConst*> (right)) {
rsig = convert_to_real_const(des, scope, tmp);
} else {
rsig = convert_to_real_const(des, right, obj);
NetNet*tmp = right->synthesize(des, scope);
rsig = cast_to_real(des, scope, tmp);
}
} else {
real_args = false;
lsig = left->synthesize(des);
rsig = right->synthesize(des);
lsig = left->synthesize(des, scope);
rsig = right->synthesize(des, scope);
}
@ -77,7 +77,7 @@ bool process_binary_args(Design*des, NetExpr*left, NetExpr*right,
else return false;
}
NetNet* NetExpr::synthesize(Design*des)
NetNet* NetExpr::synthesize(Design*des, NetScope*scope)
{
cerr << get_fileline() << ": internal error: cannot synthesize expression: "
<< *this << endl;
@ -88,25 +88,35 @@ NetNet* NetExpr::synthesize(Design*des)
/*
* Make an LPM_ADD_SUB device from addition operators.
*/
NetNet* NetEBAdd::synthesize(Design*des)
NetNet* NetEBAdd::synthesize(Design*des, NetScope*scope)
{
assert((op()=='+') || (op()=='-'));
ivl_assert(*this, (op()=='+') || (op()=='-'));
NetNet *lsig=0, *rsig=0;
bool real_args=false;
if (process_binary_args(des, left_, right_, lsig, rsig,
if (process_binary_args(des, scope, left_, right_, lsig, rsig,
real_args, this)) {
return 0;
}
assert(expr_width() >= lsig->vector_width());
assert(expr_width() >= rsig->vector_width());
ivl_assert(*this, expr_width() >= lsig->vector_width());
ivl_assert(*this, expr_width() >= rsig->vector_width());
lsig = pad_to_width(des, lsig, expr_width());
rsig = pad_to_width(des, rsig, expr_width());
unsigned width;
if (expr_type() == IVL_VT_REAL) {
width = 1;
if (lsig->data_type() != IVL_VT_REAL)
lsig = cast_to_real(des, scope, lsig);
if (rsig->data_type() != IVL_VT_REAL)
rsig = cast_to_real(des, scope, rsig);
assert(lsig->vector_width() == rsig->vector_width());
unsigned width=lsig->vector_width();
} else {
lsig = pad_to_width(des, lsig, expr_width());
rsig = pad_to_width(des, rsig, expr_width());
assert(lsig->vector_width() == rsig->vector_width());
width=lsig->vector_width();
}
perm_string path = lsig->scope()->local_symbol();
NetNet*osig = new NetNet(lsig->scope(), path, NetNet::IMPLICIT, width);
@ -138,10 +148,10 @@ NetNet* NetEBAdd::synthesize(Design*des)
* signals, then just connect a single gate to each bit of the vector
* of the expression.
*/
NetNet* NetEBBits::synthesize(Design*des)
NetNet* NetEBBits::synthesize(Design*des, NetScope*scope)
{
NetNet*lsig = left_->synthesize(des);
NetNet*rsig = right_->synthesize(des);
NetNet*lsig = left_->synthesize(des, scope);
NetNet*rsig = right_->synthesize(des, scope);
if (lsig == 0 || rsig == 0) return 0;
@ -154,10 +164,7 @@ NetNet* NetEBBits::synthesize(Design*des)
return 0;
}
NetScope*scope = lsig->scope();
assert(scope);
unsigned width = lsig->vector_width();
unsigned width = expr_width();
if (rsig->vector_width() > width) width = rsig->vector_width();
lsig = pad_to_width(des, lsig, width);
@ -205,13 +212,13 @@ NetNet* NetEBBits::synthesize(Design*des)
return osig;
}
NetNet* NetEBComp::synthesize(Design*des)
NetNet* NetEBComp::synthesize(Design*des, NetScope*scope)
{
NetNet *lsig=0, *rsig=0;
unsigned width;
bool real_args=false;
if (process_binary_args(des, left_, right_, lsig, rsig,
if (process_binary_args(des, scope, left_, right_, lsig, rsig,
real_args, this)) {
return 0;
}
@ -222,13 +229,16 @@ NetNet* NetEBComp::synthesize(Design*des)
width = lsig->vector_width();
if (rsig->vector_width() > width) width = rsig->vector_width();
lsig = pad_to_width(des, lsig, width);
rsig = pad_to_width(des, rsig, width);
if (lsig->get_signed())
lsig = pad_to_width_signed(des, lsig, width);
else
lsig = pad_to_width(des, lsig, width);
if (rsig->get_signed())
rsig = pad_to_width_signed(des, rsig, width);
else
rsig = pad_to_width(des, rsig, width);
}
NetScope*scope = lsig->scope();
assert(scope);
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, 1);
osig->set_line(*this);
@ -236,10 +246,30 @@ NetNet* NetEBComp::synthesize(Design*des)
osig->data_type(IVL_VT_LOGIC);
bool signed_compare = lsig->get_signed() && rsig->get_signed();
if (debug_elaborate) {
cerr << get_fileline() << ": debug: Comparison (" << op_ << ")"
<< " is " << (signed_compare? "signed" : "unsigned")
<< endl;
cerr << get_fileline() << ": : lsig is "
<< (lsig->get_signed()? "signed" : "unsigned")
<< " rsig is " << (rsig->get_signed()? "signed" : "unsigned")
<< endl;
}
if (op_ == 'E' || op_ == 'N') {
NetCaseCmp*gate = new NetCaseCmp(scope, scope->local_symbol(),
width, op_=='E'?true:false);
gate->set_line(*this);
connect(gate->pin(0), osig->pin(0));
connect(gate->pin(1), lsig->pin(0));
connect(gate->pin(2), rsig->pin(0));
des->add_node(gate);
return osig;
}
/* Handle the special case of a single bit equality
operation. Make an XNOR gate instead of a comparator. */
if ((width == 1) && ((op_ == 'e') || (op_ == 'E')) && !real_args) {
if ((width == 1) && (op_ == 'e') && !real_args) {
NetLogic*gate = new NetLogic(scope, scope->local_symbol(),
3, NetLogic::XNOR, 1);
gate->set_line(*this);
@ -253,7 +283,7 @@ NetNet* NetEBComp::synthesize(Design*des)
/* Handle the special case of a single bit inequality
operation. This is similar to single bit equality, but uses
an XOR instead of an XNOR gate. */
if ((width == 1) && ((op_ == 'n') || (op_ == 'N')) && !real_args) {
if ((width == 1) && (op_ == 'n') && !real_args) {
NetLogic*gate = new NetLogic(scope, scope->local_symbol(),
3, NetLogic::XOR, 1);
gate->set_line(*this);
@ -321,12 +351,12 @@ NetNet* NetEBComp::synthesize(Design*des)
return osig;
}
NetNet* NetEBPow::synthesize(Design*des)
NetNet* NetEBPow::synthesize(Design*des, NetScope*scope)
{
NetNet *lsig=0, *rsig=0;
unsigned width;
bool real_args=false;
if (process_binary_args(des, left_, right_, lsig, rsig,
if (process_binary_args(des, scope, left_, right_, lsig, rsig,
real_args, this)) {
return 0;
}
@ -334,9 +364,6 @@ NetNet* NetEBPow::synthesize(Design*des)
if (real_args) width = 1;
else width = expr_width();
NetScope*scope = lsig->scope();
assert(scope);
NetPow*powr = new NetPow(scope, scope->local_symbol(), width,
lsig->vector_width(),
rsig->vector_width());
@ -359,12 +386,12 @@ NetNet* NetEBPow::synthesize(Design*des)
return osig;
}
NetNet* NetEBMult::synthesize(Design*des)
NetNet* NetEBMult::synthesize(Design*des, NetScope*scope)
{
NetNet *lsig=0, *rsig=0;
unsigned width;
bool real_args=false;
if (process_binary_args(des, left_, right_, lsig, rsig,
if (process_binary_args(des, scope, left_, right_, lsig, rsig,
real_args, this)) {
return 0;
}
@ -372,9 +399,6 @@ NetNet* NetEBMult::synthesize(Design*des)
if (real_args) width = 1;
else width = expr_width();
NetScope*scope = lsig->scope();
assert(scope);
NetMult*mult = new NetMult(scope, scope->local_symbol(),
width,
lsig->vector_width(),
@ -398,12 +422,12 @@ NetNet* NetEBMult::synthesize(Design*des)
return osig;
}
NetNet* NetEBDiv::synthesize(Design*des)
NetNet* NetEBDiv::synthesize(Design*des, NetScope*scope)
{
NetNet *lsig=0, *rsig=0;
unsigned width;
bool real_args=false;
if (process_binary_args(des, left_, right_, lsig, rsig,
if (process_binary_args(des, scope, left_, right_, lsig, rsig,
real_args, this)) {
return 0;
}
@ -411,12 +435,11 @@ NetNet* NetEBDiv::synthesize(Design*des)
if (real_args) width = 1;
else width = expr_width();
NetScope*scope = lsig->scope();
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, width);
osig->set_line(*this);
osig->data_type(lsig->data_type());
osig->set_signed(has_sign());
osig->local_flag(true);
switch (op()) {
@ -427,6 +450,7 @@ NetNet* NetEBDiv::synthesize(Design*des)
lsig->vector_width(),
rsig->vector_width());
div->set_line(*this);
div->set_signed(has_sign());
des->add_node(div);
connect(div->pin_DataA(), lsig->pin(0));
@ -471,10 +495,10 @@ NetNet* NetEBDiv::synthesize(Design*des)
return osig;
}
NetNet* NetEBLogic::synthesize(Design*des)
NetNet* NetEBLogic::synthesize(Design*des, NetScope*scope)
{
NetNet*lsig = left_->synthesize(des);
NetNet*rsig = right_->synthesize(des);
NetNet*lsig = left_->synthesize(des, scope);
NetNet*rsig = right_->synthesize(des, scope);
if (lsig == 0 || rsig == 0) return 0;
@ -487,9 +511,6 @@ NetNet* NetEBLogic::synthesize(Design*des)
return 0;
}
NetScope*scope = lsig->scope();
assert(scope);
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, 1);
osig->data_type(expr_type());
@ -551,11 +572,11 @@ NetNet* NetEBLogic::synthesize(Design*des)
return osig;
}
NetNet* NetEBShift::synthesize(Design*des)
NetNet* NetEBShift::synthesize(Design*des, NetScope*scope)
{
eval_expr(right_);
NetNet*lsig = left_->synthesize(des);
NetNet*lsig = left_->synthesize(des, scope);
if (lsig == 0) return 0;
@ -568,10 +589,8 @@ NetNet* NetEBShift::synthesize(Design*des)
return 0;
}
bool right_flag = op_ == 'r' || op_ == 'R';
bool signed_flag = op_ == 'R';
NetScope*scope = lsig->scope();
const bool right_flag = op_ == 'r' || op_ == 'R';
const bool signed_flag = op_ == 'R';
/* Detect the special case where the shift amount is
constant. Evaluate the shift amount, and simply reconnect
@ -580,7 +599,7 @@ NetNet* NetEBShift::synthesize(Design*des)
verinum shift_v = rcon->value();
long shift = shift_v.as_long();
if (op() == 'r')
if (right_flag)
shift = 0-shift;
if (shift == 0)
@ -593,34 +612,13 @@ NetNet* NetEBShift::synthesize(Design*des)
// ushift is the amount of pad created by the shift.
unsigned long ushift = shift>=0? shift : -shift;
if (ushift > osig->vector_width())
ushift = osig->vector_width();
ivl_assert(*this, ushift < osig->vector_width());
// part_width is the bits of the vector that survive the shift.
unsigned long part_width = osig->vector_width() - ushift;
verinum znum (verinum::V0, ushift, true);
NetConst*zcon = new NetConst(scope, scope->local_symbol(),
znum);
des->add_node(zcon);
/* Detect the special case that the shift is the size of
the whole expression. Simply connect the pad to the
osig and escape. */
if (ushift >= osig->vector_width()) {
connect(zcon->pin(0), osig->pin(0));
return osig;
}
NetNet*zsig = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, znum.len());
zsig->data_type(osig->data_type());
zsig->local_flag(true);
zsig->set_line(*this);
connect(zcon->pin(0), zsig->pin(0));
/* Create a part select to reduce the width of the lsig
to the amount left by the shift. */
// Create a part select to reduce the width of the lsig
// to the amount left by the shift.
NetPartSelect*psel = new NetPartSelect(lsig, shift<0? ushift : 0,
part_width,
NetPartSelect::VP);
@ -633,6 +631,34 @@ NetNet* NetEBShift::synthesize(Design*des)
psig->set_line(*this);
connect(psig->pin(0), psel->pin(0));
// Handle the special case of a signed right shift. In
// this case, use the NetSignExtend device to pad the
// result to the desired width.
if (signed_flag && right_flag) {
NetSignExtend*pad = new NetSignExtend(scope, scope->local_symbol(),
osig->vector_width());
des->add_node(pad);
pad->set_line(*this);
connect(pad->pin(1), psig->pin(0));
connect(pad->pin(0), osig->pin(0));
return osig;
}
// Other cases are handled by zero-extending on the
// proper end.
verinum znum (verinum::V0, ushift, true);
NetConst*zcon = new NetConst(scope, scope->local_symbol(),
znum);
des->add_node(zcon);
NetNet*zsig = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, znum.len());
zsig->data_type(osig->data_type());
zsig->local_flag(true);
zsig->set_line(*this);
connect(zcon->pin(0), zsig->pin(0));
NetConcat*ccat = new NetConcat(scope, scope->local_symbol(),
osig->vector_width(), 2);
ccat->set_line(*this);
@ -652,7 +678,7 @@ NetNet* NetEBShift::synthesize(Design*des)
return osig;
}
NetNet*rsig = right_->synthesize(des);
NetNet*rsig = right_->synthesize(des, scope);
if (rsig == 0) return 0;
@ -678,13 +704,13 @@ NetNet* NetEBShift::synthesize(Design*des)
return osig;
}
NetNet* NetEConcat::synthesize(Design*des)
NetNet* NetEConcat::synthesize(Design*des, NetScope*scope)
{
/* First, synthesize the operands. */
NetNet**tmp = new NetNet*[parms_.count()];
bool flag = true;
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
tmp[idx] = parms_[idx]->synthesize(des);
tmp[idx] = parms_[idx]->synthesize(des, scope);
if (tmp[idx] == 0)
flag = false;
}
@ -692,9 +718,7 @@ NetNet* NetEConcat::synthesize(Design*des)
if (flag == false)
return 0;
assert(tmp[0]);
NetScope*scope = tmp[0]->scope();
assert(scope);
ivl_assert(*this, tmp[0]);
/* Make a NetNet object to carry the output vector. */
perm_string path = scope->local_symbol();
@ -712,7 +736,9 @@ NetNet* NetEConcat::synthesize(Design*des)
unsigned cur_pin = 1;
for (unsigned rpt = 0; rpt < repeat(); rpt += 1) {
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
connect(concat->pin(cur_pin), tmp[parms_.count()-idx-1]->pin(0));
unsigned concat_item = parms_.count()-idx-1;
ivl_assert(*this, tmp[concat_item]);
connect(concat->pin(cur_pin), tmp[concat_item]->pin(0));
cur_pin += 1;
}
}
@ -721,17 +747,14 @@ NetNet* NetEConcat::synthesize(Design*des)
return osig;
}
NetNet* NetEConst::synthesize(Design*des)
NetNet* NetEConst::synthesize(Design*des, NetScope*scope)
{
NetScope*scope = des->find_root_scope();
assert(scope);
perm_string path = scope->local_symbol();
unsigned width=expr_width();
NetNet*osig = new NetNet(scope, path, NetNet::IMPLICIT, width-1,0);
NetNet*osig = new NetNet(scope, path, NetNet::IMPLICIT, width);
osig->local_flag(true);
osig->data_type(IVL_VT_LOGIC);
osig->data_type(expr_type());
osig->set_signed(has_sign());
NetConst*con = new NetConst(scope, scope->local_symbol(), value());
connect(osig->pin(0), con->pin(0));
@ -743,11 +766,8 @@ NetNet* NetEConst::synthesize(Design*des)
/*
* Create a NetLiteral object to represent real valued constants.
*/
NetNet* NetECReal::synthesize(Design*des)
NetNet* NetECReal::synthesize(Design*des, NetScope*scope)
{
NetScope*scope = des->find_root_scope();
assert(scope);
perm_string path = scope->local_symbol();
NetNet*osig = new NetNet(scope, path, NetNet::WIRE, 1);
@ -768,9 +788,9 @@ NetNet* NetECReal::synthesize(Design*des)
* The bitwise unary logic operator (there is only one) is turned
* into discrete gates just as easily as the binary ones above.
*/
NetNet* NetEUBits::synthesize(Design*des)
NetNet* NetEUBits::synthesize(Design*des, NetScope*scope)
{
NetNet*isig = expr_->synthesize(des);
NetNet*isig = expr_->synthesize(des, scope);
if (isig == 0) return 0;
@ -782,9 +802,6 @@ NetNet* NetEUBits::synthesize(Design*des)
return 0;
}
NetScope*scope = isig->scope();
assert(scope);
unsigned width = isig->vector_width();
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, width);
@ -810,13 +827,56 @@ NetNet* NetEUBits::synthesize(Design*des)
return osig;
}
NetNet* NetEUReduce::synthesize(Design*des)
NetNet* NetEUnary::synthesize(Design*des, NetScope*scope)
{
NetNet*isig = expr_->synthesize(des);
if (op_ == '+')
return expr_->synthesize(des, scope);
if (op_ == '-') {
NetNet*sig = expr_->synthesize(des, scope);
sig = sub_net_from(des, scope, 0, sig);
return sig;
}
if (op_ == 'm') {
NetNet*sub = expr_->synthesize(des, scope);
if (expr_->has_sign() == false)
return sub;
NetNet*sig = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, sub->vector_width());
sig->set_line(*this);
sig->local_flag(true);
sig->data_type(sub->data_type());
NetAbs*tmp = new NetAbs(scope, scope->local_symbol(), sub->vector_width());
des->add_node(tmp);
tmp->set_line(*this);
connect(tmp->pin(1), sub->pin(0));
connect(tmp->pin(0), sig->pin(0));
return sig;
}
cerr << get_fileline() << ": iternal error: "
<< "NetEUnary::synthesize cannot handle op_=" << op_ << endl;
des->errors += 1;
return expr_->synthesize(des, scope);
}
NetNet* NetEUReduce::synthesize(Design*des, NetScope*scope)
{
NetNet*isig = expr_->synthesize(des, scope);
if (isig == 0) return 0;
if (isig->data_type() == IVL_VT_REAL) {
if (op() == '!') {
cerr << get_fileline() << ": sorry: ! is currently "
"unsupported for real values." << endl;
des->errors += 1;
return 0;
}
cerr << get_fileline() << ": error: reduction operator ("
<< human_readable_op(op_)
<< ") may not have a REAL operand." << endl;
@ -824,9 +884,6 @@ NetNet* NetEUReduce::synthesize(Design*des)
return 0;
}
NetScope*scope = isig->scope();
assert(scope);
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, 1);
osig->data_type(expr_type());
@ -849,7 +906,7 @@ NetNet* NetEUReduce::synthesize(Design*des)
rtype = NetUReduce::XOR;
break;
case 'A':
rtype = NetUReduce::XNOR;
rtype = NetUReduce::NAND;
break;
case 'X':
rtype = NetUReduce::XNOR;
@ -871,22 +928,101 @@ NetNet* NetEUReduce::synthesize(Design*des)
return osig;
}
NetNet* NetESelect::synthesize(Design *des)
/*
* Turn a part/bit select expression into gates.
* We know some things about the expression that elaboration enforces
* for us:
*
* - Expression elaboration already converted the offset expression into
* cannonical form, so we don't have to worry about that here.
*/
NetNet* NetESelect::synthesize(Design *des, NetScope*scope)
{
NetNet*sub = expr_->synthesize(des);
NetNet*sub = expr_->synthesize(des, scope);
if (sub == 0) return 0;
NetScope*scope = sub->scope();
NetNet*off = 0;
// Detect the special case that there is a base expression and
// it is constant. In this case we can generate fixed part selects.
if (NetEConst*base_const = dynamic_cast<NetEConst*>(base_)) {
verinum base_tmp = base_const->value();
ivl_assert(*this, base_tmp.is_defined());
long base_val = base_tmp.as_long();
unsigned select_width = expr_width();
// Any below X bits?
NetNet*below = 0;
if (base_val < 0) {
unsigned below_width = abs(base_val);
base_val = 0;
ivl_assert(*this, below_width < select_width);
select_width -= below_width;
below = make_const_x(des, scope, below_width);
below->set_line(*this);
}
// Any above bits?
NetNet*above = 0;
if ((unsigned)base_val+select_width > sub->vector_width()) {
select_width = sub->vector_width() - base_val;
unsigned above_width = expr_width() - select_width;
above = make_const_x(des, scope, above_width);
above->set_line(*this);
}
// Make the make part select.
NetPartSelect*sel = new NetPartSelect(sub, base_val, select_width,
NetPartSelect::VP);
des->add_node(sel);
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, select_width);
tmp->data_type(sub->data_type());
tmp->local_flag(true);
tmp->set_line(*this);
connect(sel->pin(0), tmp->pin(0));
unsigned concat_count = 1;
if (above)
concat_count += 1;
if (below)
concat_count += 1;
if (concat_count > 1) {
NetConcat*cat = new NetConcat(scope, scope->local_symbol(),
expr_width(), concat_count);
cat->set_line(*this);
des->add_node(cat);
if (below) {
connect(cat->pin(1), below->pin(0));
connect(cat->pin(2), tmp->pin(0));
} else {
connect(cat->pin(1), tmp->pin(0));
}
if (above) {
connect(cat->pin(concat_count), above->pin(0));
}
tmp = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, expr_width());
tmp->data_type(sub->data_type());
tmp->local_flag(true);
tmp->set_line(*this);
connect(cat->pin(0), tmp->pin(0));
}
return tmp;
}
// This handles the case that the NetESelect exists to do an
// actual part/bit select. Generate a NetPartSelect object to
// do the work, and replace "sub" with the selected output.
if (base_ != 0) {
off = base_->synthesize(des);
off = base_->synthesize(des, scope);
NetPartSelect*sel = new NetPartSelect(sub, off, expr_width());
sel->set_line(*this);
@ -967,21 +1103,26 @@ NetNet* NetESelect::synthesize(Design *des)
* expressions to the B and A inputs. This way, when the select input
* is one, the B input, which is the true expression, is selected.
*/
NetNet* NetETernary::synthesize(Design *des)
NetNet* NetETernary::synthesize(Design *des, NetScope*scope)
{
NetNet*csig = cond_->synthesize(des),
*tsig = true_val_->synthesize(des),
*fsig = false_val_->synthesize(des);
NetNet*csig = cond_->synthesize(des, scope),
*tsig = true_val_->synthesize(des, scope),
*fsig = false_val_->synthesize(des, scope);
if (csig == 0 || tsig == 0 || fsig == 0) return 0;
if (tsig->data_type() != fsig->data_type()) {
cerr << get_fileline() << ": error: True and False clauses of "
"ternary expression have different types." << endl;
if (! NetETernary::test_operand_compat(tsig->data_type(),fsig->data_type())) {
cerr << get_fileline() << ": internal error: "
<< " True and False clauses of ternary expression "
<< " have incompatible types." << endl;
cerr << get_fileline() << ": : True clause is: "
<< tsig->data_type() << endl;
<< tsig->data_type()
<< " (" << true_val_->expr_type() << "): "
<< *true_val_ << endl;
cerr << get_fileline() << ": : False clause is: "
<< fsig->data_type() << endl;
<< fsig->data_type()
<< " (" << false_val_->expr_type() << "): "
<< *false_val_ << endl;
des->errors += 1;
return 0;
} else if (tsig->data_type() == IVL_VT_NO_TYPE) {
@ -993,7 +1134,7 @@ NetNet* NetETernary::synthesize(Design *des)
perm_string path = csig->scope()->local_symbol();
assert(csig->vector_width() == 1);
ivl_assert(*this, csig->vector_width() == 1);
unsigned width=expr_width();
NetNet*osig = new NetNet(csig->scope(), path, NetNet::IMPLICIT, width);
@ -1025,26 +1166,25 @@ NetNet* NetETernary::synthesize(Design *des)
* a bit more work needs to be done. Return a temporary that represents
* the selected word.
*/
NetNet* NetESignal::synthesize(Design*des)
NetNet* NetESignal::synthesize(Design*des, NetScope*scope)
{
if (word_ == 0)
return net_;
NetScope*scope = net_->scope();
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, net_->vector_width());
tmp->set_line(*this);
tmp->local_flag(true);
tmp->data_type(net_->data_type());
// For NetExpr objects, the word index is already converted to
// a canonical (lsb==0) address. Just use the index directly.
if (NetEConst*index_co = dynamic_cast<NetEConst*> (word_)) {
long index = index_co->value().as_long();
assert(net_->array_index_is_valid(index));
index = net_->array_index_to_address(index);
connect(tmp->pin(0), net_->pin(index));
} else {
unsigned selwid = word_->expr_width();
@ -1053,7 +1193,7 @@ NetNet* NetESignal::synthesize(Design*des)
mux->set_line(*this);
des->add_node(mux);
NetNet*index_net = word_->synthesize(des);
NetNet*index_net = word_->synthesize(des, scope);
connect(mux->pin_Address(), index_net->pin(0));
connect(tmp->pin(0), mux->pin_Result());
@ -1061,22 +1201,68 @@ NetNet* NetESignal::synthesize(Design*des)
return tmp;
}
NetNet* NetESFunc::synthesize(Design*des)
NetNet* NetESFunc::synthesize(Design*des, NetScope*scope)
{
cerr << get_fileline() << ": sorry: cannot synthesize system function: "
<< *this << " in this context" << endl;
des->errors += 1;
return 0;
const struct sfunc_return_type*def = lookup_sys_func(name_);
/* We cannot use the default value for system functions in a
* continuous assignment since the function name is NULL. */
if (def == 0 || def->name == 0) {
cerr << get_fileline() << ": error: System function "
<< name_ << " not defined in system "
"table or SFT file(s)." << endl;
des->errors += 1;
return 0;
}
if (debug_elaborate) {
cerr << get_fileline() << ": debug: Net system function "
<< name_ << " returns " << def->type << endl;
}
NetSysFunc*net = new NetSysFunc(scope, scope->local_symbol(),
def, 1+nparms_);
net->set_line(*this);
des->add_node(net);
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, def->wid);
osig->local_flag(true);
osig->set_signed(def->type==IVL_VT_REAL? true : false);
osig->data_type(def->type);
osig->set_line(*this);
connect(net->pin(0), osig->pin(0));
unsigned errors = 0;
for (unsigned idx = 0 ; idx < nparms_ ; idx += 1) {
NetNet*tmp = parms_[idx]->synthesize(des, scope);
if (tmp == 0) {
cerr << get_fileline() << ": error: Unable to elaborate "
<< "argument " << idx << " of call to " << name_ <<
"." << endl;
errors += 1;
des->errors += 1;
continue;
}
connect(net->pin(1+idx), tmp->pin(0));
}
if (errors > 0) return 0;
return osig;
}
NetNet* NetEUFunc::synthesize(Design*des)
NetNet* NetEUFunc::synthesize(Design*des, NetScope*scope)
{
svector<NetNet*> eparms (parms_.count());
/* Synthesize the arguments. */
bool errors = false;
for (unsigned idx = 0; idx < eparms.count(); idx += 1) {
NetNet*tmp = parms_[idx]->synthesize(des);
NetNet*tmp = parms_[idx]->synthesize(des, scope);
if (tmp == 0) {
cerr << get_fileline() << ": error: Unable to synthesize "
"port " << idx << " of call to "

View File

@ -343,6 +343,7 @@ typedef enum ivl_signal_type_e {
typedef enum ivl_statement_type_e {
IVL_ST_NONE = 0,
IVL_ST_NOOP = 1,
IVL_ST_ALLOC = 25,
IVL_ST_ASSIGN = 2,
IVL_ST_ASSIGN_NB = 3,
IVL_ST_BLOCK = 4,
@ -359,6 +360,7 @@ typedef enum ivl_statement_type_e {
IVL_ST_FORCE = 14,
IVL_ST_FOREVER = 15,
IVL_ST_FORK = 16,
IVL_ST_FREE = 26,
IVL_ST_RELEASE = 17,
IVL_ST_REPEAT = 18,
IVL_ST_STASK = 19,
@ -502,7 +504,8 @@ extern ivl_net_const_t ivl_design_const(ivl_design_t, unsigned idx);
* ivl_const_bits
* This returns a pointer to an array of constant characters,
* each byte a '0', '1', 'x' or 'z'. The array is *not* nul
* terminated.
* terminated. This value is only value if ivl_const_type is
* IVL_VT_LOGIC or IVL_VT_BOOL. It returns nil otherwise.
*
* ivl_const_nex
* Return the ivl_nexus_t of the output for the constant.
@ -1254,7 +1257,7 @@ extern const char*ivl_lpm_string(ivl_lpm_t net);
*/
extern unsigned ivl_lval_width(ivl_lval_t net);
extern ivl_expr_t ivl_lval_mux(ivl_lval_t net); // XXXX Obsolete?
extern ivl_expr_t ivl_lval_mux(ivl_lval_t net); /* XXXX Obsolete? */
extern ivl_expr_t ivl_lval_idx(ivl_lval_t net);
extern ivl_expr_t ivl_lval_part_off(ivl_lval_t net);
extern ivl_signal_t ivl_lval_sig(ivl_lval_t net);
@ -1927,7 +1930,7 @@ extern unsigned ivl_switch_lineno(ivl_switch_t net);
#endif
extern DLLEXPORT int target_design(ivl_design_t des);
extern DLLEXPORT const char* target_query(const char*key);
/* target_design
@ -1945,6 +1948,7 @@ extern DLLEXPORT int target_design(ivl_design_t des);
ivl core. This function is how the target module is invoked. */
typedef int (*target_design_f)(ivl_design_t des);
typedef const char* (*target_query_f) (const char*key);
_END_DECL

View File

@ -40,7 +40,7 @@ INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
CPPFLAGS = @ident_support@ -I. -I.. -I$(srcdir)/.. -I$(srcdir) @CPPFLAGS@ @DEFS@
CPPFLAGS = @ident_support@ -I. -I.. -I$(srcdir)/.. -I$(srcdir) -DVERSION='"$(VERSION)"' @CPPFLAGS@ @DEFS@
CFLAGS = -Wall @CFLAGS@
LDFLAGS = @LDFLAGS@

View File

@ -698,7 +698,7 @@ static int is_defined(const char*name)
* These variables are also used for storing the actual arguments when
* a macro is instantiated.
*/
#define MAX_DEF_ARG 256 // allows argument IDs to be stored in a single char
#define MAX_DEF_ARG 256 /* allows argument IDs to be stored in a single char */
#define DEF_BUF_CHUNK 256
@ -707,14 +707,14 @@ static int def_buf_size = 0;
static int def_buf_free = 0;
static int def_argc = 0;
static int def_argo[MAX_DEF_ARG]; // offset of first character in arg
static int def_argl[MAX_DEF_ARG]; // length of arg string.
static int def_argo[MAX_DEF_ARG]; /* offset of first character in arg */
static int def_argl[MAX_DEF_ARG]; /* length of arg string. */
/*
* Return a pointer to the start of argument 'arg'. Returned pointers
* may go stale after a call to def_buf_grow_to_fit.
*/
static inline char* def_argv(int arg)
static /* inline */ char* def_argv(int arg)
{
return def_buf + def_argo[arg];
}

View File

@ -17,7 +17,8 @@ const char COPYRIGHT[] =
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
# include "config.h"
# include "config.h"
# include "version.h"
const char NOTICE[] =
" This program is free software; you can redistribute it and/or modify\n"
@ -35,8 +36,6 @@ const char NOTICE[] =
" Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA\n"
;
const char VERSION[] = "$Name: $ $State: Exp $";
# include <stdio.h>
# include <stdlib.h>
#ifdef HAVE_MALLOC_H
@ -103,6 +102,8 @@ static int flist_read_flags(const char*path)
char*cp = line_buf + strspn(line_buf, " \t\r\b\f");
/* Remove trailing white space. */
char*tail = cp + strlen(cp);
char*arg;
while (tail > cp) {
if (! isspace(tail[-1]))
break;
@ -118,7 +119,7 @@ static int flist_read_flags(const char*path)
continue;
/* The arg points to the argument to the keyword. */
char*arg = strchr(cp, ':');
arg = strchr(cp, ':');
if (arg) *arg++ = 0;
if (strcmp(cp,"D") == 0) {
@ -229,7 +230,7 @@ int main(int argc, char*argv[])
include_dir[0] = 0; /* 0 is reserved for the current files path. */
include_dir[1] = strdup(".");
while ((opt=getopt(argc, argv, "F:f:K:Lo:p:P:v")) != EOF) switch (opt) {
while ((opt=getopt(argc, argv, "F:f:K:Lo:p:P:vV")) != EOF) switch (opt) {
case 'F':
flist_read_flags(optarg);
@ -284,12 +285,19 @@ int main(int argc, char*argv[])
}
case 'v':
fprintf(stderr, "Icarus Verilog Preprocessor version %s\n",
VERSION);
fprintf(stderr, "Icarus Verilog Preprocessor version "
VERSION " (" VERSION_TAG ")\n\n");
fprintf(stderr, "%s\n", COPYRIGHT);
fputs(NOTICE, stderr);
break;
case 'V':
fprintf(stdout, "Icarus Verilog Preprocessor version "
VERSION " (" VERSION_TAG ")\n\n");
fprintf(stdout, "%s\n", COPYRIGHT);
fputs(NOTICE, stdout);
return 0;
default:
flag_errors += 1;
break;
@ -304,7 +312,8 @@ int main(int argc, char*argv[])
" -o<fil> - Send the output to <fil>\n"
" -p<fil> - Write precompiled defines to <fil>\n"
" -P<fil> - Read precompiled defines from <fil>\n"
" -v - Print version information\n",
" -v - Verbose\n"
" -V - Print version information and quit\n",
argv[0]);
return flag_errors;
}

View File

@ -87,6 +87,7 @@ static void process_timescale(const char*txt);
static list<int> keyword_mask_stack;
static int comment_enter;
static bool in_module = false;
%}
%x CCOMMENT
@ -123,8 +124,8 @@ S [afpnumkKMGT]
/* The contents of C-style comments are ignored, like white space. */
"/*" { comment_enter = YY_START; BEGIN(CCOMMENT); }
<CCOMMENT>. { yymore(); }
<CCOMMENT>\n { yylloc.first_line += 1; yymore(); }
<CCOMMENT>. { ; }
<CCOMMENT>\n { yylloc.first_line += 1; }
<CCOMMENT>"*/" { BEGIN(comment_enter); }
@ -227,6 +228,15 @@ S [afpnumkKMGT]
BEGIN(EDGES);
break;
case K_module:
case K_macromodule:
in_module = true;
break;
case K_endmodule:
in_module = false;
break;
default:
yylval.text = 0;
break;
@ -343,6 +353,12 @@ S [afpnumkKMGT]
^{W}?`timescale { BEGIN(PPTIMESCALE); }
<PPTIMESCALE>.* { process_timescale(yytext); }
<PPTIMESCALE>\n {
if (in_module) {
cerr << yylloc.text << ":" << yylloc.first_line << ": error: "
"`timescale directive can not be inside a module "
"definition." << endl;
error_count += 1;
}
yylloc.first_line += 1;
BEGIN(0); }
@ -439,7 +455,7 @@ S [afpnumkKMGT]
} else {
cerr << yylloc.text << ":" << yylloc.first_line
<< " error: Net type " << yytext
<< ": error: Net type " << yytext
<< " is not a valid (and supported)"
<< " default net type." << endl;
net_type = NetNet::WIRE;
@ -457,37 +473,37 @@ S [afpnumkKMGT]
^{W}?`define{W}?.* {
cerr << yylloc.text << ":" << yylloc.first_line <<
": `define not supported. Use an external preprocessor."
": warning: `define not supported. Use an external preprocessor."
<< endl;
}
^{W}?`else{W}?.* {
cerr << yylloc.text << ":" << yylloc.first_line <<
": `else not supported. Use an external preprocessor."
": warning: `else not supported. Use an external preprocessor."
<< endl;
}
^{W}?`endif{W}?.* {
cerr << yylloc.text << ":" << yylloc.first_line <<
": `endif not supported. Use an external preprocessor."
": warning: `endif not supported. Use an external preprocessor."
<< endl;
}
^{W}?`ifdef{W}?.* {
cerr << yylloc.text << ":" << yylloc.first_line <<
": `ifdef not supported. Use an external preprocessor."
": warning: `ifdef not supported. Use an external preprocessor."
<< endl;
}
^`include{W}?.* {
cerr << yylloc.text << ":" << yylloc.first_line <<
": `include not supported. Use an external preprocessor."
": warning: `include not supported. Use an external preprocessor."
<< endl;
}
^`undef{W}?.* {
cerr << yylloc.text << ":" << yylloc.first_line <<
": `undef not supported. Use an external preprocessor."
": warning: `undef not supported. Use an external preprocessor."
<< endl;
}

View File

@ -99,7 +99,7 @@ PLI_INT32 acc_fetch_fulltype(handle obj)
return accTopModule;
else
return accModuleInstance;
// FIXME accCellInstance
/* FIXME accCellInstance */
case vpiNamedEvent: return accNamedEvent;

View File

@ -55,7 +55,7 @@ handle acc_next(PLI_INT32 *type, handle scope, handle prev)
* rescan all the items up to the previous one, then return
* the next one.
*/
iter = vpi_iterate(vpiScope, scope); // ICARUS extension
iter = vpi_iterate(vpiScope, scope); /* ICARUS extension */
if (prev) {
while ((hand = vpi_scan(iter))) {
if (hand == prev) break;

View File

@ -366,7 +366,7 @@ PLI_INT32 tf_isetrealdelay(double dly, void*obj)
s_cb_data cb;
s_vpi_time ti = {vpiSimTime};
// Scale delay to SimTime
/* Scale delay to SimTime */
ivl_u64_t delay = ((dly
* pow(10, tf_gettimeprecision() - tf_gettimeunit()))
+ 0.5);

56
main.cc
View File

@ -20,6 +20,7 @@ const char COPYRIGHT[] =
*/
# include "config.h"
# include "version.h"
const char NOTICE[] =
" This program is free software; you can redistribute it and/or modify\n"
@ -59,6 +60,7 @@ const char NOTICE[] =
# include "target.h"
# include "compiler.h"
# include "discipline.h"
# include "t-dll.h"
#if defined(__MINGW32__) && !defined(HAVE_GETOPT_H)
extern "C" int getopt(int argc, char*argv[], const char*fmt);
@ -75,12 +77,8 @@ extern "C" const char*optarg;
/* Count errors detected in flag processing. */
unsigned flag_errors = 0;
const char VERSION[] = "$Name: $";
const char*basedir = ".";
const char*target = "null";
/*
* These are the language support control flags. These support which
* language features (the generation) to support. The generation_flag
@ -293,7 +291,7 @@ static void find_module_mention(map<perm_string,bool>&check_map, PGenerate*s);
* -T:<min/typ/max>
* Select which expression to use.
*
* -t:<target>
* -t:<target> (obsolete)
* Usually, "-t:dll"
*
* basedir:<path>
@ -483,7 +481,7 @@ static void read_iconfig_file(const char*ipath)
library_suff.push_back(strdup(cp));
} else if (strcmp(buf,"-t") == 0) {
target = strdup(cp);
// NO LONGER USED
} else if (strcmp(buf,"-T") == 0) {
if (strcmp(cp,"min") == 0) {
@ -533,6 +531,7 @@ int main(int argc, char*argv[])
{
bool help_flag = false;
bool times_flag = false;
bool version_flag = false;
const char* net_path = 0;
const char* pf_path = 0;
@ -576,10 +575,8 @@ int main(int argc, char*argv[])
# endif
break;
case 'V':
cout << "Icarus Verilog version " << VERSION << endl;
cout << COPYRIGHT << endl;
cout << endl << NOTICE << endl;
return 0;
version_flag = true;
break;
default:
flag_errors += 1;
break;
@ -588,8 +585,20 @@ int main(int argc, char*argv[])
if (flag_errors)
return flag_errors;
if (version_flag) {
cout << "\n\nIcarus Verilog Parser/Elaborator version "
<< VERSION << " (" << VERSION_TAG << ")" << endl;
cout << COPYRIGHT << endl;
cout << endl << NOTICE << endl;
dll_target_obj.test_version(flags["DLL"]);
return 0;
}
if (help_flag) {
cout << "Icarus Verilog version " << VERSION << endl <<
cout << "Icarus Verilog Parser/Elaborator version "
<< VERSION << " (" << VERSION_TAG << ")" << endl <<
"usage: ivl <options> <file>\n"
"options:\n"
"\t-C <name> Config file from driver.\n"
@ -844,20 +853,21 @@ int main(int argc, char*argv[])
}
if (verbose_flag) {
cout << "CODE GENERATION -t "<<target<< endl;
cout << "CODE GENERATION" << endl;
}
int emit_rc;
emit_rc = emit(des, target);
if (emit_rc > 0) {
cerr << "error: Code generation had "
<< emit_rc << " errors."
<< endl;
return 1;
}
if (emit_rc < 0) {
cerr << "error: Code generator failure: " << emit_rc << endl;
return -1;
if (int emit_rc = des->emit(&dll_target_obj)) {
if (emit_rc > 0) {
cerr << "error: Code generation had "
<< emit_rc << " errors."
<< endl;
return 1;
}
if (emit_rc < 0) {
cerr << "error: Code generator failure: " << emit_rc << endl;
return -1;
}
assert(emit_rc);
}
if (verbose_flag) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2008 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -16,9 +16,6 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: net_assign.cc,v 1.22 2007/01/16 05:44:15 steve Exp $"
#endif
# include "config.h"
@ -84,6 +81,11 @@ unsigned NetAssign_::lwidth() const
return lwid_;
}
ivl_variable_type_t NetAssign_::expr_type() const
{
return sig_->data_type();
}
perm_string NetAssign_::name() const
{
if (sig_) {
@ -212,15 +214,34 @@ NetAssign::~NetAssign()
{
}
NetAssignNB::NetAssignNB(NetAssign_*lv, NetExpr*rv)
NetAssignNB::NetAssignNB(NetAssign_*lv, NetExpr*rv, NetEvWait*ev, NetExpr*cnt)
: NetAssignBase(lv, rv)
{
event_ = ev;
count_ = cnt;
}
NetAssignNB::~NetAssignNB()
{
}
unsigned NetAssignNB::nevents() const
{
if (event_) return event_->nevents();
return 0;
}
const NetEvent*NetAssignNB::event(unsigned idx) const
{
if (event_) return event_->event(idx);
return 0;
}
const NetExpr*NetAssignNB::get_count() const
{
return count_;
}
NetCAssign::NetCAssign(NetAssign_*lv, NetExpr*rv)
: NetAssignBase(lv, rv)
{
@ -256,34 +277,3 @@ NetRelease::NetRelease(NetAssign_*l)
NetRelease::~NetRelease()
{
}
/*
* $Log: net_assign.cc,v $
* Revision 1.22 2007/01/16 05:44:15 steve
* Major rework of array handling. Memories are replaced with the
* more general concept of arrays. The NetMemory and NetEMemory
* classes are removed from the ivl core program, and the IVL_LPM_RAM
* lpm type is removed from the ivl_target API.
*
* Revision 1.21 2006/02/02 02:43:58 steve
* Allow part selects of memory words in l-values.
*
* Revision 1.20 2005/07/11 16:56:50 steve
* Remove NetVariable and ivl_variable_t structures.
*
* Revision 1.19 2004/12/11 02:31:26 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.18 2004/08/28 15:08:31 steve
* Do not change reg to wire in NetAssign_ unless synthesizing.
*
* Revision 1.17 2004/02/18 17:11:56 steve
* Use perm_strings for named langiage items.
*
* Revision 1.16 2003/01/26 21:15:58 steve
* Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions.
*/

View File

@ -251,7 +251,6 @@ NetEvProbe::NetEvProbe(NetScope*s, perm_string n, NetEvent*tgt,
{
for (unsigned idx = 0 ; idx < p ; idx += 1) {
pin(idx).set_dir(Link::INPUT);
pin(idx).set_name(perm_string::literal("P"), idx);
}
enext_ = event_->probes_;

View File

@ -127,6 +127,9 @@ ivl_variable_type_t NetEBAdd::expr_type() const
NetEBComp::NetEBComp(char op, NetExpr*l, NetExpr*r)
: NetEBinary(op, l, r)
{
// The output of compare is always unsigned.
cast_signed_base_(false);
if (NetEConst*tmp = dynamic_cast<NetEConst*>(r)) do {
if (tmp->has_width())
@ -242,7 +245,11 @@ ivl_variable_type_t NetEBMinMax::expr_type() const
NetEBMult::NetEBMult(char op, NetExpr*l, NetExpr*r)
: NetEBinary(op, l, r)
{
expr_width(l->expr_width() + r->expr_width());
if (expr_type() == IVL_VT_REAL)
expr_width(1);
else
expr_width(l->expr_width() + r->expr_width());
cast_signed(l->has_sign() && r->has_sign());
/* If it turns out that this is not a signed expression, then
@ -302,10 +309,6 @@ ivl_variable_type_t NetEBPow::expr_type() const
return IVL_VT_REAL;
if (left_->expr_type() == IVL_VT_REAL)
return IVL_VT_REAL;
if (left_->has_sign())
return IVL_VT_REAL;
if (right_->has_sign())
return IVL_VT_REAL;
return IVL_VT_LOGIC;
}

View File

@ -34,12 +34,10 @@ NetUserFunc::NetUserFunc(NetScope*s, perm_string n, NetScope*d)
def_(d)
{
pin(0).set_dir(Link::OUTPUT);
pin(0).set_name(def_->basename(), 0);
for (unsigned idx = 1 ; idx < pin_count() ; idx += 1) {
pin(idx).set_dir(Link::INPUT);
pin(idx).set_name(perm_string::literal("D"), idx-1);
pin(idx).drive0(Link::HIGHZ);
pin(idx).drive1(Link::HIGHZ);
}
@ -135,13 +133,11 @@ NetSysFunc::NetSysFunc(NetScope*s, perm_string n,
{
def_ = def;
pin(0).set_dir(Link::OUTPUT);
pin(0).set_name(perm_string::literal("Q"), 0);
pin(0).set_dir(Link::OUTPUT); // Q
for (unsigned idx = 1 ; idx < pin_count() ; idx += 1) {
pin(idx).set_dir(Link::INPUT);
pin(idx).set_name(perm_string::literal("D"), idx-1);
pin(idx).drive0(Link::HIGHZ);
pin(idx).drive1(Link::HIGHZ);
}

View File

@ -64,7 +64,7 @@ void connect(Link&l, Link&r)
Link::Link()
: dir_(PASSIVE), drive0_(STRONG), drive1_(STRONG), init_(verinum::Vx),
inst_(0), next_(0), nexus_(0)
next_(0), nexus_(0)
{
(new Nexus()) -> relink(this);
}
@ -103,6 +103,11 @@ void Link::drivers_delays(NetExpr*rise, NetExpr*fall, NetExpr*decay)
nexus_->drivers_delays(rise, fall, decay);
}
void Link::drivers_drive(strength_t drive0, strength_t drive1)
{
nexus_->drivers_drive(drive0, drive1);
}
void Link::drive0(Link::strength_t str)
{
drive0_ = str;
@ -136,14 +141,14 @@ verinum::V Link::get_init() const
void Link::cur_link(NetPins*&net, unsigned &pin)
{
net = node_;
pin = pin_;
net = get_obj();
pin = get_pin();
}
void Link::cur_link(const NetPins*&net, unsigned &pin) const
{
net = node_;
pin = pin_;
net = get_obj();
pin = get_pin();
}
void Link::unlink()
@ -188,33 +193,28 @@ const Link* Link::next_nlink() const
const NetPins*Link::get_obj() const
{
return node_;
if (pin_zero_)
return node_;
const Link*tmp = this - pin_;
assert(tmp->pin_zero_);
return tmp->node_;
}
NetPins*Link::get_obj()
{
return node_;
if (pin_zero_)
return node_;
Link*tmp = this - pin_;
assert(tmp->pin_zero_);
return tmp->node_;
}
unsigned Link::get_pin() const
{
return pin_;
}
void Link::set_name(perm_string n, unsigned i)
{
name_ = n;
inst_ = i;
}
perm_string Link::get_name() const
{
return name_;
}
unsigned Link::get_inst() const
{
return inst_;
if (pin_zero_)
return 0;
else
return pin_;
}
Nexus::Nexus()
@ -298,6 +298,17 @@ void Nexus::drivers_delays(NetExpr*rise, NetExpr*fall, NetExpr*decay)
}
}
void Nexus::drivers_drive(Link::strength_t drive0, Link::strength_t drive1)
{
for (Link*cur = list_ ; cur ; cur = cur->next_) {
if (cur->get_dir() != Link::OUTPUT)
continue;
cur->drive0(drive0);
cur->drive1(drive1);
}
}
void Nexus::unlink(Link*that)
{
if (name_) {
@ -437,10 +448,9 @@ const char* Nexus::name() const
const Link*lnk = first_nlink();
const NetObj*obj = dynamic_cast<const NetObj*>(lnk->get_obj());
pin = lnk->get_pin();
cerr << "internal error: No signal for nexus of " <<
obj->name() << " pin " << pin << "(" <<
lnk->get_name() << "<" << lnk->get_inst() << ">)"
" type=" << typeid(*obj).name() << "?" << endl;
cerr << "internal error: No signal for nexus of "
<< obj->name() << " pin " << pin
<< " type=" << typeid(*obj).name() << "?" << endl;
}
assert(sig);

View File

@ -40,12 +40,9 @@ NetModulo::NetModulo(NetScope*s, perm_string n, unsigned wr,
: NetNode(s, n, 3),
width_r_(wr), width_a_(wa), width_b_(wb)
{
pin(0).set_dir(Link::OUTPUT);
pin(0).set_name(perm_string::literal("Result"), 0);
pin(1).set_dir(Link::INPUT);
pin(1).set_name(perm_string::literal("DataA"), 0);
pin(2).set_dir(Link::INPUT);
pin(2).set_name(perm_string::literal("DataB"), 0);
pin(0).set_dir(Link::OUTPUT); // Result
pin(1).set_dir(Link::INPUT); // DataA
pin(2).set_dir(Link::INPUT); // DataB
}
NetModulo::~NetModulo()

View File

@ -45,19 +45,18 @@ static bool has_enable(ivl_switch_type_t tt)
NetTran::NetTran(NetScope*scope, perm_string n, ivl_switch_type_t tt)
: NetNode(scope, n, has_enable(tt)? 3 : 2), type_(tt)
{
pin(0).set_dir(Link::PASSIVE); pin(0).set_name(perm_string::literal("A"), 0);
pin(1).set_dir(Link::PASSIVE); pin(1).set_name(perm_string::literal("B"), 0);
pin(0).set_dir(Link::PASSIVE);
pin(1).set_dir(Link::PASSIVE);
if (pin_count() == 3) {
pin(2).set_dir(Link::INPUT);
pin(2).set_name(perm_string::literal("E"), 0);
pin(2).set_dir(Link::INPUT); // Enable
}
}
NetTran::NetTran(NetScope*scope, perm_string n, unsigned wid, unsigned part, unsigned off)
: NetNode(scope, n, 2), type_(IVL_SW_TRAN_VP), wid_(wid), part_(part), off_(off)
{
pin(0).set_dir(Link::PASSIVE); pin(0).set_name(perm_string::literal("A"), 0);
pin(1).set_dir(Link::PASSIVE); pin(1).set_name(perm_string::literal("B"), 0);
pin(0).set_dir(Link::PASSIVE);
pin(1).set_dir(Link::PASSIVE);
}
NetTran::~NetTran()

View File

@ -30,10 +30,8 @@ NetUDP::NetUDP(NetScope*s, perm_string n, unsigned pins, PUdp *u)
: NetNode(s, n, pins), udp(u)
{
pin(0).set_dir(Link::OUTPUT);
pin(0).set_name(perm_string::literal("O"), 0);
for (unsigned idx = 1 ; idx < pins ; idx += 1) {
pin(idx).set_dir(Link::INPUT);
pin(idx).set_name(perm_string::literal("I"), idx-1);
}
}

View File

@ -23,6 +23,7 @@
# include <typeinfo>
# include <cstdlib>
# include <climits>
# include "compiler.h"
# include "netlist.h"
# include "netmisc.h"
@ -175,9 +176,12 @@ NetPins::NetPins(unsigned npins)
: npins_(npins)
{
pins_ = new Link[npins_];
for (unsigned idx = 0 ; idx < npins_ ; idx += 1) {
pins_[idx].node_ = this;
pins_[idx].pin_ = idx;
pins_[0].pin_zero_ = true;
pins_[0].node_ = this;
for (unsigned idx = 1 ; idx < npins_ ; idx += 1) {
pins_[idx].pin_zero_ = false;
pins_[idx].pin_ = idx;
}
}
@ -196,12 +200,15 @@ Link& NetPins::pin(unsigned idx)
}
assert(idx < npins_);
assert(idx == 0? pins_[0].pin_zero_ : pins_[idx].pin_==idx);
return pins_[idx];
}
const Link& NetPins::pin(unsigned idx) const
{
assert(idx < npins_);
assert(idx == 0? pins_[0].pin_zero_ : pins_[idx].pin_==idx);
return pins_[idx];
}
@ -238,9 +245,7 @@ NetNode::~NetNode()
NetBranch::NetBranch(discipline_t*dis)
: NetPins(2), discipline_(dis)
{
pin(0).set_name(perm_string::literal("A"), 0);
pin(0).set_dir(Link::PASSIVE);
pin(1).set_name(perm_string::literal("B"), 0);
pin(1).set_dir(Link::PASSIVE);
}
@ -266,13 +271,11 @@ NetDelaySrc::NetDelaySrc(NetScope*s, perm_string n, unsigned npins,
posedge_ = false;
negedge_ = false;
for (unsigned idx = 0 ; idx < npins ; idx += 1) {
pin(idx).set_name(perm_string::literal("I"), idx);
pin(idx).set_dir(Link::INPUT);
}
if (condit_src) {
condit_flag_ = true;
pin(npins).set_name(perm_string::literal("COND"), 0);
pin(npins).set_dir(Link::INPUT);
}
}
@ -455,7 +458,6 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t, unsigned npins)
break;
}
pin(0).set_name(perm_string::literal("P"), 0);
pin(0).set_dir(dir);
pin(0).set_init(init_value);
@ -494,7 +496,6 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t,
}
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
pin(idx).set_name(perm_string::literal("P"), idx);
pin(idx).set_dir(dir);
pin(idx).set_init(init_value);
}
@ -542,7 +543,6 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t,
}
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
pin(idx).set_name(perm_string::literal("P"), idx);
pin(idx).set_dir(dir);
pin(idx).set_init(init_value);
}
@ -627,7 +627,10 @@ void NetNet::data_type(ivl_variable_type_t t)
bool NetNet::get_signed() const
{
return signed_;
if (data_type_ == IVL_VT_REAL)
return true;
else
return signed_;
}
void NetNet::set_signed(bool flag)
@ -796,8 +799,6 @@ NetPartSelect::NetPartSelect(NetNet*sig, unsigned off, unsigned wid,
pin(1).set_dir(Link::OUTPUT);
break;
}
pin(0).set_name(perm_string::literal("Part"), 0);
pin(1).set_name(perm_string::literal("Vect"), 0);
}
NetPartSelect::NetPartSelect(NetNet*sig, NetNet*sel,
@ -819,10 +820,6 @@ NetPartSelect::NetPartSelect(NetNet*sig, NetNet*sel,
break;
}
pin(2).set_dir(Link::INPUT);
pin(0).set_name(perm_string::literal("Part"), 0);
pin(1).set_name(perm_string::literal("Vect"), 0);
pin(2).set_name(perm_string::literal("Select"), 0);
}
NetPartSelect::~NetPartSelect()
@ -887,28 +884,22 @@ NetCastInt::NetCastInt(NetScope*scope, perm_string n, unsigned width)
: NetNode(scope, n, 2), width_(width)
{
pin(0).set_dir(Link::OUTPUT);
pin(0).set_name(perm_string::literal("O"), 0);
pin(1).set_dir(Link::INPUT);
pin(1).set_name(perm_string::literal("I"), 0);
}
NetCastReal::NetCastReal(NetScope*scope, perm_string n, bool signed_flag)
: NetNode(scope, n, 2), signed_flag_(signed_flag)
{
pin(0).set_dir(Link::OUTPUT);
pin(0).set_name(perm_string::literal("O"), 0);
pin(1).set_dir(Link::INPUT);
pin(1).set_name(perm_string::literal("I"), 0);
}
NetConcat::NetConcat(NetScope*scope, perm_string n, unsigned wid, unsigned cnt)
: NetNode(scope, n, cnt+1), width_(wid)
{
pin(0).set_dir(Link::OUTPUT);
pin(0).set_name(perm_string::literal("O"), 0);
for (unsigned idx = 1 ; idx < cnt+1 ; idx += 1) {
pin(idx).set_dir(Link::INPUT);
pin(idx).set_name(perm_string::literal("I"), idx-1);
}
}
@ -926,9 +917,7 @@ NetReplicate::NetReplicate(NetScope*scope, perm_string n,
: NetNode(scope, n, 2), width_(wid), repeat_(rpt)
{
pin(0).set_dir(Link::OUTPUT);
pin(0).set_name(perm_string::literal("O"), 0);
pin(1).set_dir(Link::INPUT);
pin(1).set_name(perm_string::literal("I"), 0);
}
NetReplicate::~NetReplicate()
@ -963,21 +952,13 @@ NetFF::NetFF(NetScope*s, perm_string n, unsigned width)
: NetNode(s, n, 8), width_(width)
{
pin_Clock().set_dir(Link::INPUT);
pin_Clock().set_name(perm_string::literal("Clock"), 0);
pin_Enable().set_dir(Link::INPUT);
pin_Enable().set_name(perm_string::literal("Enable"), 0);
pin_Aset().set_dir(Link::INPUT);
pin_Aset().set_name(perm_string::literal("Aset"), 0);
pin_Aclr().set_dir(Link::INPUT);
pin_Aclr().set_name(perm_string::literal("Aclr"), 0);
pin_Sset().set_dir(Link::INPUT);
pin_Sset().set_name(perm_string::literal("Sset"), 0);
pin_Sclr().set_dir(Link::INPUT);
pin_Sclr().set_name(perm_string::literal("Sclr"), 0);
pin_Data().set_dir(Link::INPUT);
pin_Data().set_name(perm_string::literal("Data"), 0);
pin_Q().set_dir(Link::OUTPUT);
pin_Q().set_name(perm_string::literal("Q"), 0);
}
NetFF::~NetFF()
@ -1094,9 +1075,7 @@ NetAbs::NetAbs(NetScope*s, perm_string n, unsigned w)
: NetNode(s, n, 2), width_(w)
{
pin(0).set_dir(Link::OUTPUT);
pin(0).set_name(perm_string::literal("Result"), 0);
pin(1).set_dir(Link::INPUT);
pin(1).set_name(perm_string::literal("DataA"), 0);
}
NetAbs::~NetAbs()
@ -1111,37 +1090,18 @@ unsigned NetAbs::width() const
/*
* The NetAddSub class represents an LPM_ADD_SUB device. The pinout is
* assigned like so:
* 0 -- Add_Sub
* 1 -- Aclr
* 2 -- Clock
* 3 -- Cin
* 4 -- Cout
* 5 -- Overflow
* 6 -- DataA (normally a vector)
* 7 -- DataB (normally a vector)
* 8 -- Result (normally a vector)
* 0 -- Cout
* 1 -- DataA (normally a vector)
* 2 -- DataB (normally a vector)
* 3 -- Result (normally a vector)
*/
NetAddSub::NetAddSub(NetScope*s, perm_string n, unsigned w)
: NetNode(s, n, 9), width_(w)
: NetNode(s, n, 4), width_(w)
{
pin(0).set_dir(Link::INPUT);
pin(0).set_name(perm_string::literal("Add_Sub"), 0);
pin(1).set_dir(Link::INPUT);
pin(1).set_name(perm_string::literal("Aclr"), 0);
pin(2).set_dir(Link::INPUT);
pin(2).set_name(perm_string::literal("Clock"), 0);
pin(3).set_dir(Link::INPUT);
pin(3).set_name(perm_string::literal("Cin"), 0);
pin(4).set_dir(Link::OUTPUT);
pin(4).set_name(perm_string::literal("Cout"), 0);
pin(5).set_dir(Link::OUTPUT);
pin(5).set_name(perm_string::literal("Overflow"), 0);
pin(6).set_dir(Link::INPUT);
pin(6).set_name(perm_string::literal("DataA"), 0);
pin(7).set_dir(Link::INPUT);
pin(7).set_name(perm_string::literal("DataB"), 0);
pin(8).set_dir(Link::OUTPUT);
pin(8).set_name(perm_string::literal("Result"), 0);
pin(0).set_dir(Link::OUTPUT); // Cout
pin(1).set_dir(Link::INPUT); // DataA
pin(2).set_dir(Link::INPUT); // DataB
pin(3).set_dir(Link::OUTPUT); // Result
}
NetAddSub::~NetAddSub()
@ -1155,52 +1115,50 @@ unsigned NetAddSub::width()const
Link& NetAddSub::pin_Cout()
{
return pin(4);
return pin(0);
}
const Link& NetAddSub::pin_Cout() const
{
return pin(4);
return pin(0);
}
Link& NetAddSub::pin_DataA()
{
return pin(6);
return pin(1);
}
const Link& NetAddSub::pin_DataA() const
{
return pin(6);
return pin(1);
}
Link& NetAddSub::pin_DataB()
{
return pin(7);
return pin(2);
}
const Link& NetAddSub::pin_DataB() const
{
return pin(7);
return pin(2);
}
Link& NetAddSub::pin_Result()
{
return pin(8);
return pin(3);
}
const Link& NetAddSub::pin_Result() const
{
return pin(8);
return pin(3);
}
NetArrayDq::NetArrayDq(NetScope*s, perm_string n, NetNet*mem, unsigned awid)
: NetNode(s, n, 2),
mem_(mem), awidth_(awid)
{
pin(0).set_dir(Link::OUTPUT);
pin(0).set_name(perm_string::literal("Result"), 0);
pin(1).set_dir(Link::INPUT);
pin(1).set_name(perm_string::literal("Address"), 0);
pin(0).set_dir(Link::OUTPUT); // Result
pin(1).set_dir(Link::INPUT); // Address
// Increment the expression reference count for the target
// memory so that it is not deleted underneath me.
mem->incr_eref();
@ -1258,12 +1216,9 @@ NetCLShift::NetCLShift(NetScope*s, perm_string n,
width_(width), width_dist_(width_dist),
right_flag_(right_flag), signed_flag_(signed_flag)
{
pin(0).set_dir(Link::OUTPUT);
pin(0).set_name(perm_string::literal("Result"), 0);
pin(1).set_dir(Link::INPUT);
pin(1).set_name(perm_string::literal("Data"), 0);
pin(2).set_dir(Link::INPUT);
pin(2).set_name(perm_string::literal("Distance"), 0);
pin(0).set_dir(Link::OUTPUT); // Result
pin(1).set_dir(Link::INPUT); // Data
pin(2).set_dir(Link::INPUT); // Distance
}
NetCLShift::~NetCLShift()
@ -1324,26 +1279,16 @@ NetCompare::NetCompare(NetScope*s, perm_string n, unsigned wi)
: NetNode(s, n, 10), width_(wi)
{
signed_flag_ = false;
pin(0).set_dir(Link::INPUT); pin(0).set_name(
perm_string::literal("Aclr"));
pin(1).set_dir(Link::INPUT); pin(1).set_name(
perm_string::literal("Clock"));
pin(2).set_dir(Link::OUTPUT); pin(2).set_name(
perm_string::literal("AGB"));
pin(3).set_dir(Link::OUTPUT); pin(3).set_name(
perm_string::literal("AGEB"));
pin(4).set_dir(Link::OUTPUT); pin(4).set_name(
perm_string::literal("AEB"));
pin(5).set_dir(Link::OUTPUT); pin(5).set_name(
perm_string::literal("ANEB"));
pin(6).set_dir(Link::OUTPUT); pin(6).set_name(
perm_string::literal("ALB"));
pin(7).set_dir(Link::OUTPUT); pin(7).set_name(
perm_string::literal("ALEB"));
pin(8).set_dir(Link::INPUT);
pin(8).set_name(perm_string::literal("DataA"));
pin(9).set_dir(Link::INPUT);
pin(9).set_name(perm_string::literal("DataB"));
pin(0).set_dir(Link::INPUT); // Aclr
pin(1).set_dir(Link::INPUT); // Clock
pin(2).set_dir(Link::OUTPUT); // AGB
pin(3).set_dir(Link::OUTPUT); // AGEB
pin(4).set_dir(Link::OUTPUT); // AEB
pin(5).set_dir(Link::OUTPUT); // ANEB
pin(6).set_dir(Link::OUTPUT); // ALB
pin(7).set_dir(Link::OUTPUT); // ALEB
pin(8).set_dir(Link::INPUT); // DataA
pin(9).set_dir(Link::INPUT); // DataB
}
NetCompare::~NetCompare()
@ -1365,6 +1310,7 @@ void NetCompare::set_signed(bool flag)
signed_flag_ = flag;
}
Link& NetCompare::pin_Aclr()
{
return pin(0);
@ -1470,12 +1416,9 @@ NetDivide::NetDivide(NetScope*sc, perm_string n, unsigned wr,
: NetNode(sc, n, 3),
width_r_(wr), width_a_(wa), width_b_(wb), signed_flag_(false)
{
pin(0).set_dir(Link::OUTPUT);
pin(0).set_name(perm_string::literal("Result"), 0);
pin(1).set_dir(Link::INPUT);
pin(1).set_name(perm_string::literal("DataA"), 0);
pin(2).set_dir(Link::INPUT);
pin(2).set_name(perm_string::literal("DataB"), 0);
pin(0).set_dir(Link::OUTPUT); // Result
pin(1).set_dir(Link::INPUT); // DataA
pin(2).set_dir(Link::INPUT); // DataB
}
NetDivide::~NetDivide()
@ -1541,7 +1484,6 @@ NetLiteral::NetLiteral(NetScope*sc, perm_string n, const verireal&val)
: NetNode(sc, n, 1), real_(val)
{
pin(0).set_dir(Link::OUTPUT);
pin(0).set_name(perm_string::literal("O"), 0);
}
NetLiteral::~NetLiteral()
@ -1563,12 +1505,9 @@ NetMult::NetMult(NetScope*sc, perm_string n, unsigned wr,
: NetNode(sc, n, 3),
signed_(false), width_r_(wr), width_a_(wa), width_b_(wb)
{
pin(0).set_dir(Link::OUTPUT);
pin(0).set_name(perm_string::literal("Result"), 0);
pin(1).set_dir(Link::INPUT);
pin(1).set_name(perm_string::literal("DataA"), 0);
pin(2).set_dir(Link::INPUT);
pin(2).set_name(perm_string::literal("DataB"), 0);
pin(0).set_dir(Link::OUTPUT); // Result
pin(1).set_dir(Link::INPUT); // DataA
pin(2).set_dir(Link::INPUT); // DataB
}
NetMult::~NetMult()
@ -1635,12 +1574,9 @@ NetPow::NetPow(NetScope*sc, perm_string n, unsigned wr,
: NetNode(sc, n, 3),
signed_(false), width_r_(wr), width_a_(wa), width_b_(wb)
{
pin(0).set_dir(Link::OUTPUT);
pin(0).set_name(perm_string::literal("Result"), 0);
pin(1).set_dir(Link::INPUT);
pin(1).set_name(perm_string::literal("DataA"), 0);
pin(2).set_dir(Link::INPUT);
pin(2).set_name(perm_string::literal("DataB"), 0);
pin(0).set_dir(Link::OUTPUT); // Result
pin(1).set_dir(Link::INPUT); // DataA
pin(2).set_dir(Link::INPUT); // DataB
}
NetPow::~NetPow()
@ -1715,14 +1651,11 @@ NetMux::NetMux(NetScope*s, perm_string n,
: NetNode(s, n, 2+si),
width_(wi), size_(si), swidth_(sw)
{
pin(0).set_dir(Link::OUTPUT);
pin(0).set_name(perm_string::literal("Q"), 0);
pin(1).set_dir(Link::INPUT);
pin(1).set_name(perm_string::literal("Sel"), 0);
pin(0).set_dir(Link::OUTPUT); // Q
pin(1).set_dir(Link::INPUT); // Sel
for (unsigned idx = 0 ; idx < size_ ; idx += 1) {
pin_Data(idx).set_dir(Link::INPUT);
pin_Data(idx).set_name(perm_string::literal("D"), idx);
pin_Data(idx).set_dir(Link::INPUT); // Data[idx]
}
}
@ -1782,8 +1715,6 @@ NetSignExtend::NetSignExtend(NetScope*s, perm_string n, unsigned w)
{
pin(0).set_dir(Link::OUTPUT);
pin(1).set_dir(Link::INPUT);
pin(0).set_name(perm_string::literal("O"), 0);
pin(1).set_name(perm_string::literal("I"), 0);
}
NetSignExtend::~NetSignExtend()
@ -1800,8 +1731,6 @@ NetBUFZ::NetBUFZ(NetScope*s, perm_string n, unsigned w)
{
pin(0).set_dir(Link::OUTPUT);
pin(1).set_dir(Link::INPUT);
pin(0).set_name(perm_string::literal("O"), 0);
pin(1).set_name(perm_string::literal("I"), 0);
}
NetBUFZ::~NetBUFZ()
@ -1816,9 +1745,9 @@ unsigned NetBUFZ::width() const
NetCaseCmp::NetCaseCmp(NetScope*s, perm_string n, unsigned wid, bool eeq)
: NetNode(s, n, 3), width_(wid), eeq_(eeq)
{
pin(0).set_dir(Link::OUTPUT); pin(0).set_name(perm_string::literal("O"),0);
pin(1).set_dir(Link::INPUT); pin(1).set_name(perm_string::literal("I"),0);
pin(2).set_dir(Link::INPUT); pin(2).set_name(perm_string::literal("I"),1);
pin(0).set_dir(Link::OUTPUT);
pin(1).set_dir(Link::INPUT);
pin(2).set_dir(Link::INPUT);
}
NetCaseCmp::~NetCaseCmp()
@ -1877,7 +1806,6 @@ NetConst::NetConst(NetScope*s, perm_string n, verinum::V v)
: NetNode(s, n, 1), width_(1)
{
pin(0).set_dir(Link::OUTPUT);
pin(0).set_name(perm_string::literal("O"), 0);
value_ = new verinum::V[1];
value_[0] = v;
}
@ -1886,7 +1814,6 @@ NetConst::NetConst(NetScope*s, perm_string n, const verinum&val)
: NetNode(s, n, 1), width_(val.len())
{
pin(0).set_dir(Link::OUTPUT);
pin(0).set_name(perm_string::literal("O"), 0);
value_ = new verinum::V[width_];
for (unsigned idx = 0 ; idx < width_ ; idx += 1) {
value_[idx] = val.get(idx);
@ -1917,12 +1844,7 @@ NetFuncDef::NetFuncDef(NetScope*s, NetNet*result, const svector<NetNet*>&po)
NetFuncDef::~NetFuncDef()
{
}
#if 0
const string NetFuncDef::name() const
{
return scope_->name();
}
#endif
const NetScope* NetFuncDef::scope() const
{
return scope_;
@ -2046,17 +1968,50 @@ NetUTask::NetUTask(NetScope*def)
NetUTask::~NetUTask()
{
}
#if 0
const string NetUTask::name() const
{
return task_->name();
}
#endif
const NetScope* NetUTask::task() const
{
return task_;
}
NetAlloc::NetAlloc(NetScope*scope)
: scope_(scope)
{
}
NetAlloc::~NetAlloc()
{
}
#if 0
const string NetAlloc::name() const
{
return scope_->name();
}
#endif
const NetScope* NetAlloc::scope() const
{
return scope_;
}
NetFree::NetFree(NetScope*scope)
: scope_(scope)
{
}
NetFree::~NetFree()
{
}
#if 0
const string NetFree::name() const
{
return scope_->name();
}
#endif
const NetScope* NetFree::scope() const
{
return scope_;
}
NetExpr::NetExpr(unsigned w)
: width_(w), signed_flag_(false)
{
@ -2076,6 +2031,13 @@ void NetExpr::cast_signed(bool flag)
signed_flag_ = flag;
}
void NetExpr::expr_width(unsigned w)
{
// Catch underflow wrap errors.
ivl_assert(*this, w < (UINT_MAX - 256));
width_ = w;
}
bool NetExpr::has_width() const
{
return true;
@ -2111,6 +2073,9 @@ NetEBBits* NetEBBits::dup_expr() const
NetEBinary::NetEBinary(char op, NetExpr*l, NetExpr*r)
: op_(op), left_(l), right_(r)
{
// Binary expressions of all sorts are signed if both the
// arguments are signed.
cast_signed_base_( left_->has_sign() && right_->has_sign());
}
NetEBinary::~NetEBinary()
@ -2329,6 +2294,8 @@ const NetExpr* NetETernary::false_expr() const
ivl_variable_type_t NetETernary::expr_type() const
{
ivl_assert(*this, true_val_);
ivl_assert(*this, false_val_);
ivl_variable_type_t tru = true_val_->expr_type();
ivl_variable_type_t fal = false_val_->expr_type();
if (tru == IVL_VT_LOGIC && fal == IVL_VT_BOOL)
@ -2413,10 +2380,8 @@ NetLogic::NetLogic(NetScope*s, perm_string n, unsigned pins,
: NetNode(s, n, pins), type_(t), width_(wid)
{
pin(0).set_dir(Link::OUTPUT);
pin(0).set_name(perm_string::literal("O"), 0);
for (unsigned idx = 1 ; idx < pins ; idx += 1) {
pin(idx).set_dir(Link::INPUT);
pin(idx).set_name(perm_string::literal("I"), idx-1);
}
}
@ -2435,9 +2400,7 @@ NetUReduce::NetUReduce(NetScope*scope, perm_string n,
: NetNode(scope, n, 2), type_(t), width_(wid)
{
pin(0).set_dir(Link::OUTPUT);
pin(0).set_name(perm_string::literal("O"));
pin(1).set_dir(Link::INPUT);
pin(1).set_name(perm_string::literal("I"));
}
NetUReduce::TYPE NetUReduce::type() const

146
netlist.h
View File

@ -89,7 +89,7 @@ class NetPins : public LineInfo {
Link&pin(unsigned idx);
const Link&pin(unsigned idx) const;
void dump_node_pins(ostream&, unsigned) const;
void dump_node_pins(ostream&, unsigned, const char**pin_names =0) const;
private:
Link*pins_;
@ -194,9 +194,11 @@ class Link {
enum strength_t { HIGHZ, WEAK, PULL, STRONG, SUPPLY };
private: // Only NetPins can create/delete Link objects
Link();
~Link();
public:
// Manipulate the link direction.
void set_dir(DIR d);
DIR get_dir() const;
@ -210,6 +212,10 @@ class Link {
void drive0(strength_t);
void drive1(strength_t);
// This sets the drives for all drivers of this link, and not
// just the current link.
void drivers_drive(strength_t d0, strength_t d1);
strength_t drive0() const;
strength_t drive1() const;
@ -252,28 +258,19 @@ class Link {
NetPins*get_obj();
unsigned get_pin() const;
// A link of an object (sometimes called a "pin") has a
// name. It is convenient for the name to have a string and an
// integer part.
void set_name(perm_string, unsigned inst =0);
perm_string get_name() const;
unsigned get_inst() const;
private:
// The NetNode manages these. They point back to the
// NetNode so that following the links can get me here.
NetPins *node_;
unsigned pin_;
union {
NetPins *node_;
unsigned pin_;
};
DIR dir_;
strength_t drive0_, drive1_;
verinum::V init_;
// These members name the pin of the link. If the name
// has width, then the inst_ member is the index of the
// pin.
perm_string name_;
unsigned inst_;
bool pin_zero_ : 1;
DIR dir_ : 2;
strength_t drive0_ : 3;
strength_t drive1_ : 3;
verinum::V init_ : 2;
private:
Link *next_;
@ -312,6 +309,7 @@ class Nexus {
verinum::V get_init() const;
void drivers_delays(NetExpr*rise, NetExpr*fall, NetExpr*decay);
void drivers_drive(Link::strength_t d0, Link::strength_t d1);
Link*first_nlink();
const Link* first_nlink()const;
@ -914,13 +912,7 @@ class NetAddSub : public NetNode {
// operands and results).
unsigned width() const;
Link& pin_Aclr();
Link& pin_Add_Sub();
Link& pin_Clock();
Link& pin_Cin();
Link& pin_Cout();
Link& pin_Overflow();
Link& pin_DataA();
Link& pin_DataB();
Link& pin_Result();
@ -1576,12 +1568,20 @@ class NetExpr : public LineInfo {
virtual NexusSet* nex_input(bool rem_out = true) =0;
// Return a version of myself that is structural. This is used
// for converting expressions to gates.
virtual NetNet*synthesize(Design*);
// for converting expressions to gates. The arguments are:
//
// des, scope: The context where this work is done
//
// rise/fall/decay: Attach these delays to the driver for the
// expression output.
//
// drive0/drive1: Attach these strengths tp the driver for
// the expression output.
virtual NetNet*synthesize(Design*des, NetScope*scope);
protected:
void expr_width(unsigned w) { width_ = w; }
void expr_width(unsigned w);
void cast_signed_base_(bool flag) {signed_flag_ = flag; }
private:
@ -1615,7 +1615,7 @@ class NetEConst : public NetExpr {
virtual void dump(ostream&) const;
virtual NetEConst* dup_expr() const;
virtual NetNet*synthesize(Design*);
virtual NetNet*synthesize(Design*, NetScope*scope);
virtual NexusSet* nex_input(bool rem_out = true);
private:
@ -1632,7 +1632,7 @@ class NetEConstParam : public NetEConst {
perm_string name() const;
const NetScope*scope() const;
virtual bool set_width(unsigned w, bool last_chance);
virtual bool set_width(unsigned w, bool last_chance =false);
virtual void expr_scan(struct expr_scan_t*) const;
virtual void dump(ostream&) const;
@ -1668,7 +1668,7 @@ class NetECReal : public NetExpr {
virtual void dump(ostream&) const;
virtual NetECReal* dup_expr() const;
virtual NetNet*synthesize(Design*);
virtual NetNet*synthesize(Design*, NetScope*scope);
virtual NexusSet* nex_input(bool rem_out = true);
private:
@ -2086,6 +2086,23 @@ class NetProc : public virtual LineInfo {
NetProc& operator= (const NetProc&);
};
class NetAlloc : public NetProc {
public:
NetAlloc(NetScope*);
~NetAlloc();
const string name() const;
const NetScope* scope() const;
virtual bool emit_proc(struct target_t*) const;
virtual void dump(ostream&, unsigned ind) const;
private:
NetScope*scope_;
};
/*
* Procedural assignment is broken into a suite of classes. These
* classes represent the various aspects of the assignment statement
@ -2139,6 +2156,7 @@ class NetAssign_ {
// method accounts for the presence of the mux, so it is not
// necessarily the same as the pin_count().
unsigned lwidth() const;
ivl_variable_type_t expr_type() const;
// Get the name of the underlying object.
perm_string name() const;
@ -2230,7 +2248,8 @@ class NetAssign : public NetAssignBase {
class NetAssignNB : public NetAssignBase {
public:
explicit NetAssignNB(NetAssign_*lv, NetExpr*rv);
explicit NetAssignNB(NetAssign_*lv, NetExpr*rv, NetEvWait*ev,
NetExpr*cnt);
~NetAssignNB();
@ -2238,7 +2257,13 @@ class NetAssignNB : public NetAssignBase {
virtual int match_proc(struct proc_match_t*);
virtual void dump(ostream&, unsigned ind) const;
unsigned nevents() const;
const NetEvent*event(unsigned) const;
const NetExpr* get_count() const;
private:
NetEvWait*event_;
NetExpr*count_;
};
/*
@ -2620,6 +2645,8 @@ class NetEvWait : public NetProc {
const svector<NetEvProbe*>&events);
virtual void dump(ostream&, unsigned ind) const;
// This will ignore any statement.
virtual void dump_inline(ostream&) const;
virtual DelayType delay_type() const;
private:
@ -2629,6 +2656,8 @@ class NetEvWait : public NetProc {
NetEvent**events_;
};
ostream& operator << (ostream&out, const NetEvWait&obj);
class NetEvProbe : public NetNode {
friend class NetEvent;
@ -2694,6 +2723,23 @@ class NetForever : public NetProc {
NetProc*statement_;
};
class NetFree : public NetProc {
public:
NetFree(NetScope*);
~NetFree();
const string name() const;
const NetScope* scope() const;
virtual bool emit_proc(struct target_t*) const;
virtual void dump(ostream&, unsigned ind) const;
private:
NetScope*scope_;
};
/*
* A function definition is elaborated just like a task, though by now
* it is certain that the first parameter (a phantom parameter) is the
@ -2905,7 +2951,7 @@ class NetEUFunc : public NetExpr {
virtual void expr_scan(struct expr_scan_t*) const;
virtual NetEUFunc*dup_expr() const;
virtual NexusSet* nex_input(bool rem_out = true);
virtual NetNet* synthesize(Design*des);
virtual NetNet* synthesize(Design*des, NetScope*scope);
private:
NetScope*scope_;
@ -3120,7 +3166,7 @@ class NetEBAdd : public NetEBinary {
virtual bool set_width(unsigned w, bool last_chance);
virtual NetEBAdd* dup_expr() const;
virtual NetExpr* eval_tree(int prune_to_width = -1);
virtual NetNet* synthesize(Design*);
virtual NetNet* synthesize(Design*, NetScope*scope);
private:
NetECReal* eval_tree_real_();
@ -3142,7 +3188,7 @@ class NetEBDiv : public NetEBinary {
virtual bool set_width(unsigned w, bool last_chance);
virtual NetEBDiv* dup_expr() const;
virtual NetExpr* eval_tree(int prune_to_width = -1);
virtual NetNet* synthesize(Design*);
virtual NetNet* synthesize(Design*, NetScope*scope);
};
/*
@ -3169,7 +3215,7 @@ class NetEBBits : public NetEBinary {
virtual NetEBBits* dup_expr() const;
virtual NetEConst* eval_tree(int prune_to_width = -1);
virtual NetNet* synthesize(Design*);
virtual NetNet* synthesize(Design*, NetScope*scope);
};
/*
@ -3200,7 +3246,7 @@ class NetEBComp : public NetEBinary {
virtual NetEBComp* dup_expr() const;
virtual NetEConst* eval_tree(int prune_to_width = -1);
virtual NetNet* synthesize(Design*);
virtual NetNet* synthesize(Design*, NetScope*scope);
private:
NetEConst* must_be_leeq_(NetExpr*le, const verinum&rv, bool eq_flag);
@ -3232,7 +3278,7 @@ class NetEBLogic : public NetEBinary {
virtual bool set_width(unsigned w, bool last_chance);
virtual NetEBLogic* dup_expr() const;
virtual NetEConst* eval_tree(int prune_to_width = -1);
virtual NetNet* synthesize(Design*);
virtual NetNet* synthesize(Design*, NetScope*scope);
private:
};
@ -3270,7 +3316,7 @@ class NetEBMult : public NetEBinary {
virtual bool set_width(unsigned w, bool last_chance);
virtual NetEBMult* dup_expr() const;
virtual NetExpr* eval_tree(int prune_to_width = -1);
virtual NetNet* synthesize(Design*);
virtual NetNet* synthesize(Design*, NetScope*scope);
private:
@ -3292,7 +3338,7 @@ class NetEBPow : public NetEBinary {
virtual bool set_width(unsigned w, bool last_chance);
virtual NetEBPow* dup_expr() const;
virtual NetExpr* eval_tree(int prune_to_width = -1);
virtual NetNet* synthesize(Design*);
virtual NetNet* synthesize(Design*, NetScope*scope);
private:
@ -3324,7 +3370,7 @@ class NetEBShift : public NetEBinary {
virtual NetEBShift* dup_expr() const;
virtual NetEConst* eval_tree(int prune_to_width = -1);
virtual NetNet* synthesize(Design*);
virtual NetNet* synthesize(Design*, NetScope*scope);
private:
};
@ -3358,7 +3404,7 @@ class NetEConcat : public NetExpr {
virtual bool set_width(unsigned w, bool last_chance =false);
virtual NetEConcat* dup_expr() const;
virtual NetEConst* eval_tree(int prune_to_width = -1);
virtual NetNet*synthesize(Design*);
virtual NetNet*synthesize(Design*, NetScope*scope);
virtual void expr_scan(struct expr_scan_t*) const;
virtual void dump(ostream&) const;
@ -3434,7 +3480,7 @@ class NetESelect : public NetExpr {
virtual void expr_scan(struct expr_scan_t*) const;
virtual NetEConst* eval_tree(int prune_to_width = -1);
virtual NetESelect* dup_expr() const;
virtual NetNet*synthesize(Design*des);
virtual NetNet*synthesize(Design*des, NetScope*scope);
virtual void dump(ostream&) const;
private:
@ -3514,7 +3560,7 @@ class NetESFunc : public NetExpr {
virtual void expr_scan(struct expr_scan_t*) const;
virtual NetESFunc*dup_expr() const;
virtual NetNet*synthesize(Design*);
virtual NetNet*synthesize(Design*, NetScope*scope);
private:
const char* name_;
@ -3551,7 +3597,10 @@ class NetETernary : public NetExpr {
virtual NexusSet* nex_input(bool rem_out = true);
virtual void expr_scan(struct expr_scan_t*) const;
virtual void dump(ostream&) const;
virtual NetNet*synthesize(Design*);
virtual NetNet*synthesize(Design*, NetScope*scope);
public:
static bool test_operand_compat(ivl_variable_type_t tru, ivl_variable_type_t fal);
private:
NetExpr*cond_;
@ -3588,6 +3637,7 @@ class NetEUnary : public NetExpr {
virtual NetEUnary* dup_expr() const;
virtual NetExpr* eval_tree(int prune_to_width = -1);
virtual NetNet* synthesize(Design*, NetScope*scope);
virtual ivl_variable_type_t expr_type() const;
virtual NexusSet* nex_input(bool rem_out = true);
@ -3608,7 +3658,7 @@ class NetEUBits : public NetEUnary {
NetEUBits(char op, NetExpr*ex);
~NetEUBits();
virtual NetNet* synthesize(Design*);
virtual NetNet* synthesize(Design*, NetScope*scope);
virtual NetExpr* eval_tree(int prune_to_width = -1);
virtual ivl_variable_type_t expr_type() const;
@ -3621,7 +3671,7 @@ class NetEUReduce : public NetEUnary {
~NetEUReduce();
virtual bool set_width(unsigned w, bool last_chance);
virtual NetNet* synthesize(Design*);
virtual NetNet* synthesize(Design*, NetScope*scope);
virtual NetEUReduce* dup_expr() const;
virtual NetEConst* eval_tree(int prune_to_width = -1);
virtual ivl_variable_type_t expr_type() const;
@ -3648,7 +3698,7 @@ class NetESignal : public NetExpr {
virtual bool set_width(unsigned, bool last_chance);
virtual NetESignal* dup_expr() const;
NetNet* synthesize(Design*des);
NetNet* synthesize(Design*des, NetScope*scope);
NexusSet* nex_input(bool rem_out = true);
// This is the expression for selecting an array word, if this

View File

@ -76,6 +76,46 @@ NetNet* add_to_net(Design*des, NetNet*sig, long val)
#endif
}
NetNet* sub_net_from(Design*des, NetScope*scope, long val, NetNet*sig)
{
NetNet*zero_net = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, sig->vector_width());
zero_net->data_type(sig->data_type());
zero_net->local_flag(true);
if (sig->data_type() == IVL_VT_REAL) {
verireal zero (val);
NetLiteral*zero_obj = new NetLiteral(scope, scope->local_symbol(), zero);
des->add_node(zero_obj);
connect(zero_net->pin(0), zero_obj->pin(0));
} else {
verinum zero ((int64_t)val);
zero = pad_to_width(zero, sig->vector_width());
NetConst*zero_obj = new NetConst(scope, scope->local_symbol(), zero);
des->add_node(zero_obj);
connect(zero_net->pin(0), zero_obj->pin(0));
}
NetAddSub*adder = new NetAddSub(scope, scope->local_symbol(), sig->vector_width());
des->add_node(adder);
adder->attribute(perm_string::literal("LPM_Direction"), verinum("SUB"));
connect(zero_net->pin(0), adder->pin_DataA());
connect(adder->pin_DataB(), sig->pin(0));
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, sig->vector_width());
tmp->data_type(sig->data_type());
tmp->local_flag(true);
connect(adder->pin_Result(), tmp->pin(0));
return tmp;
}
NetNet* cast_to_int(Design*des, NetScope*scope, NetNet*src, unsigned wid)
{
if (src->data_type() != IVL_VT_REAL)
@ -170,6 +210,27 @@ NetEConst* make_const_x(unsigned long wid)
return resx;
}
NetEConst* make_const_0(unsigned long wid)
{
verinum xxx (verinum::V0, wid);
NetEConst*resx = new NetEConst(xxx);
return resx;
}
NetNet* make_const_x(Design*des, NetScope*scope, unsigned long wid)
{
verinum xxx (verinum::Vx, wid);
NetConst*res = new NetConst(scope, scope->local_symbol(), xxx);
des->add_node(res);
NetNet*sig = new NetNet(scope, scope->local_symbol(), NetNet::WIRE, wid);
sig->local_flag(true);
sig->data_type(IVL_VT_LOGIC);
connect(sig->pin(0), res->pin(0));
return sig;
}
NetExpr* condition_reduce(NetExpr*expr)
{
if (expr->expr_width() == 1)
@ -317,26 +378,28 @@ const char *human_readable_op(const char op)
{
const char *type;
switch (op) {
case '~': type = "~"; break; // Negation
case '~': type = "~"; break; // Negation
case '^': type = "^"; break; // XOR
case 'X': type = "~^"; break; // XNOR
case '&': type = "&"; break; // Bitwise AND
case 'A': type = "~&"; break; // NAND (~&)
case '|': type = "|"; break; // Bitwise OR
case 'O': type = "~|"; break; // NOR
case '^': type = "^"; break; // XOR
case 'X': type = "~^"; break; // XNOR
case '&': type = "&"; break; // Bitwise AND
case 'A': type = "~&"; break; // NAND (~&)
case '|': type = "|"; break; // Bitwise OR
case 'O': type = "~|"; break; // NOR
case 'a': type = "&&"; break; // Logical AND
case 'o': type = "||"; break; // Logical OR
case '!': type = "!"; break; // Logical NOT
case 'a': type = "&&"; break; // Logical AND
case 'o': type = "||"; break; // Logical OR
case 'E': type = "==="; break; // Case equality
case 'N': type = "!=="; break; // Case inequality
case 'E': type = "==="; break; // Case equality
case 'N': type = "!=="; break; // Case inequality
case 'l': type = "<<(<)"; break; // Left shifts
case 'r': type = ">>"; break; // Logical right shift
case 'R': type = ">>>"; break; // Arithmetic right shift
case 'l': type = "<<(<)"; break; // Left shifts
case 'r': type = ">>"; break; // Logical right shift
case 'R': type = ">>>"; break; // Arithmetic right shift
default: assert(0);
default:
assert(0);
}
return type;
}

View File

@ -91,6 +91,7 @@ extern NetNet*crop_to_width(Design*des, NetNet*n, unsigned w);
* return a new NetNet value that is the output of an addition.
*/
extern NetNet*add_to_net(Design*des, NetNet*sig, long val);
extern NetNet*sub_net_from(Design*des, NetScope*scope, long val, NetNet*sig);
/*
* These functions make various sorts of expressions, given operands
@ -113,6 +114,12 @@ extern NetExpr*make_sub_expr(long val, NetExpr*expr);
* Make a NetEConst object that contains only X bits.
*/
extern NetEConst*make_const_x(unsigned long wid);
extern NetEConst*make_const_0(unsigned long wid);
/*
* Make A const net
*/
extern NetNet* make_const_x(Design*des, NetScope*scope, unsigned long wid);
/*
* In some cases the lval is accessible as a pointer to the head of
@ -130,14 +137,27 @@ extern unsigned count_lval_width(const class NetAssign_*first);
* The expr_width is the width of the context where the expression is
* being elaborated, or -1 if the expression is self-determined width.
*
* Also, the prune_width is the maximum width of the result, and it
* passed to the eval_tree method of the expression to limit constant
* results if possible.
* The prune_width is the maximum width of the result, and is passed
* to the eval_tree method of the expression to limit constant
* results. The evaluation will prune any constant result down to the
* prune_width (if >0) so should only be used at the point where it is
* bound to the destination.
*/
class PExpr;
extern NetExpr* elab_and_eval(Design*des, NetScope*scope,
const PExpr*pe, int expr_wid,
int prune_width =-1);
/*
* This function elaborates an expression as if it is for the r-value
* of an assignment, The data_type_lv and expr_wid_lv are the type and
* with of the l-value, and the expr is the expression to
* elaborate. The result is the NetExpr elaborated and evaluated.
* (See elab_expr.cc)
*/
extern NetExpr* elaborate_rval_expr(Design*des, NetScope*scope,
ivl_variable_type_t data_type_lv,
int expr_wid_lv, const PExpr*expr);
/*
* This procedure elaborates an expression and if the elaboration is
* successful the original expression is replaced with the new one.
@ -165,6 +185,13 @@ extern hname_t eval_path_component(Design*des, NetScope*scope,
extern std::list<hname_t> eval_scope_path(Design*des, NetScope*scope,
const pform_name_t&path);
/*
* Return true if the data type is a type that is normally available
* in vector for. IVL_VT_BOOL and IVL_VT_LOGIC are vectorable,
* IVL_VT_REAL is not.
*/
extern bool type_is_vectorable(ivl_variable_type_t type);
/*
* Return a human readable version of the operator.
*/

View File

@ -88,6 +88,7 @@ NetNet*pad_to_width(Design*des, NetNet*net, unsigned wid)
tmp = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, wid);
tmp->data_type( net->data_type() );
tmp->set_line(*net);
tmp->local_flag(true);
connect(cc->pin(0), tmp->pin(0));

17
parse.y
View File

@ -157,7 +157,7 @@ static PECallFunction*make_call_function(perm_string tn, PExpr*arg1, PExpr*arg2)
svector<lgate>*gates;
Module::port_t *mport;
Module::range_t* value_range;
LexicalScope::range_t* value_range;
svector<Module::port_t*>*mports;
named_pexpr_t*named_pexpr;
@ -459,10 +459,14 @@ block_item_decl
with real value. Note that real and realtime are interchangeable
in this context. */
| attribute_list_opt K_real real_variable_list ';'
{ delete $3; }
| attribute_list_opt K_realtime real_variable_list ';'
{ delete $3; }
| attribute_list_opt K_real real_variable_list ';'
{ delete $3; }
| attribute_list_opt K_realtime real_variable_list ';'
{ delete $3; }
| K_event list_of_identifiers ';'
{ pform_make_events($2, @1.text, @1.first_line);
}
| K_parameter parameter_assign_decl ';'
| K_localparam localparam_assign_decl ';'
@ -2036,9 +2040,6 @@ module_item
/* */
| K_defparam defparam_assign_list ';'
| K_event list_of_identifiers ';'
{ pform_make_events($2, @1.text, @1.first_line);
}
/* Most gate types have an optional drive strength and optional
three-value delay. These rules handle the different cases. */

View File

@ -170,52 +170,39 @@ void pform_bind_attributes(map<perm_string,PExpr*>&attributes,
delete attr;
}
static LexicalScope*pform_get_cur_scope()
{
if (pform_cur_generate)
if (pform_cur_generate->lexical_scope)
return pform_cur_generate->lexical_scope;
else
return pform_cur_generate;
else
return lexical_scope;
}
PWire*pform_get_wire_in_scope(perm_string name)
{
/* Note that if we are processing a generate, then the
scope depth will be empty because generate schemes
cannot be within sub-scopes. Only directly in
modules. */
if (pform_cur_generate)
if (pform_cur_generate->lexical_scope)
return pform_cur_generate->lexical_scope->wires_find(name);
else
return pform_cur_generate->wires_find(name);
else
return lexical_scope->wires_find(name);
return pform_get_cur_scope()->wires_find(name);
}
static void pform_put_wire_in_scope(perm_string name, PWire*net)
{
if (pform_cur_generate)
if (pform_cur_generate->lexical_scope)
pform_cur_generate->lexical_scope->wires[name] = net;
else
pform_cur_generate->wires[name] = net;
else
lexical_scope->wires[name] = net;
pform_get_cur_scope()->wires[name] = net;
}
static void pform_put_behavior_in_scope(PProcess*pp)
{
if (pform_cur_generate)
if (pform_cur_generate->lexical_scope)
pform_cur_generate->lexical_scope->behaviors.push_back(pp);
else
pform_cur_generate->behaviors.push_back(pp);
else
lexical_scope->behaviors.push_back(pp);
pform_get_cur_scope()->behaviors.push_back(pp);
}
void pform_put_behavior_in_scope(AProcess*pp)
{
if (pform_cur_generate)
if (pform_cur_generate->lexical_scope)
pform_cur_generate->lexical_scope->analog_behaviors.push_back(pp);
else
pform_cur_generate->analog_behaviors.push_back(pp);
else
lexical_scope->analog_behaviors.push_back(pp);
pform_get_cur_scope()->analog_behaviors.push_back(pp);
}
void pform_set_default_nettype(NetNet::Type type,
@ -1045,7 +1032,7 @@ static void pform_make_event(perm_string name, const char*fn, unsigned ln)
{
PEvent*event = new PEvent(name);
FILE_NAME(event, fn, ln);
pform_cur_module->events[name] = event;
pform_get_cur_scope()->events[name] = event;
}
void pform_make_events(list<perm_string>*names, const char*fn, unsigned ln)
@ -1705,7 +1692,7 @@ void pform_set_reg_idx(perm_string name, PExpr*l, PExpr*r)
cur->set_memory_idx(l, r);
}
Module::range_t* pform_parameter_value_range(bool exclude_flag,
LexicalScope::range_t* pform_parameter_value_range(bool exclude_flag,
bool low_open, PExpr*low_expr,
bool hig_open, PExpr*hig_expr)
{
@ -1714,7 +1701,7 @@ Module::range_t* pform_parameter_value_range(bool exclude_flag,
if (low_expr == 0) low_open = false;
if (hig_expr == 0) hig_open = false;
Module::range_t*tmp = new Module::range_t;
LexicalScope::range_t*tmp = new LexicalScope::range_t;
tmp->exclude_flag = exclude_flag;
tmp->low_open_flag = low_open;
tmp->low_expr = low_expr;
@ -1727,10 +1714,15 @@ Module::range_t* pform_parameter_value_range(bool exclude_flag,
void pform_set_parameter(const struct vlltype&loc,
perm_string name, ivl_variable_type_t type,
bool signed_flag, svector<PExpr*>*range, PExpr*expr,
Module::range_t*value_range)
LexicalScope::range_t*value_range)
{
if (pform_get_cur_scope() == pform_cur_generate) {
VLerror("parameter declarations are not permitted in generate blocks");
return;
}
assert(expr);
Module::param_expr_t&parm = pform_cur_module->parameters[name];
Module::param_expr_t&parm = pform_get_cur_scope()->parameters[name];
FILE_NAME(&parm, loc);
parm.expr = expr;
@ -1749,7 +1741,8 @@ void pform_set_parameter(const struct vlltype&loc,
parm.signed_flag = signed_flag;
parm.range = value_range;
pform_cur_module->param_names.push_back(name);
if (pform_get_cur_scope() == pform_cur_module)
pform_cur_module->param_names.push_back(name);
}
void pform_set_localparam(const struct vlltype&loc,
@ -1757,7 +1750,7 @@ void pform_set_localparam(const struct vlltype&loc,
bool signed_flag, svector<PExpr*>*range, PExpr*expr)
{
assert(expr);
Module::param_expr_t&parm = pform_cur_module->localparams[name];
Module::param_expr_t&parm = pform_get_cur_scope()->localparams[name];
FILE_NAME(&parm, loc);
parm.expr = expr;

View File

@ -272,7 +272,7 @@ extern void pform_set_attrib(perm_string name, perm_string key,
extern void pform_set_type_attrib(perm_string name, const string&key,
char*value);
extern Module::range_t* pform_parameter_value_range(bool exclude_flag,
extern LexicalScope::range_t* pform_parameter_value_range(bool exclude_flag,
bool low_open, PExpr*low_expr,
bool hig_open, PExpr*hig_expr);
@ -281,7 +281,7 @@ extern void pform_set_parameter(const struct vlltype&loc,
ivl_variable_type_t type,
bool signed_flag,
svector<PExpr*>*range,
PExpr*expr, Module::range_t*value_range);
PExpr*expr, LexicalScope::range_t*value_range);
extern void pform_set_localparam(const struct vlltype&loc,
perm_string name,
ivl_variable_type_t type,

View File

@ -78,7 +78,7 @@ void pform_end_nature(const struct vlltype&loc)
error_count += 1;
}
// Map the access functio back to the nature so that
// Map the access function back to the nature so that
// expressions that use the access function can find it.
access_function_nature[nature_access] = tmp;

View File

@ -295,6 +295,9 @@ void PEBinary::dump(ostream&out) const
case 'l':
out << "<<";
break;
case 'L':
out << "<=";
break;
case 'n':
out << "!=";
break;
@ -592,8 +595,15 @@ void PBlock::dump(ostream&out, unsigned ind) const
out << " : " << pscope_name();
out << endl;
if (pscope_name() != 0)
if (pscope_name() != 0) {
dump_parameters_(out, ind+2);
dump_localparams_(out, ind+2);
dump_events_(out, ind+2);
dump_wires_(out, ind+2);
}
for (unsigned idx = 0 ; idx < list_.count() ; idx += 1) {
if (list_[idx])
@ -812,6 +822,12 @@ void PFunction::dump(ostream&out, unsigned ind) const
out << (*ports_)[idx]->basename() << ";" << endl;
}
dump_parameters_(out, ind);
dump_localparams_(out, ind);
dump_events_(out, ind);
dump_wires_(out, ind);
if (statement_)
@ -857,6 +873,12 @@ void PTask::dump(ostream&out, unsigned ind) const
out << (*ports_)[idx]->basename() << ";" << endl;
}
dump_parameters_(out, ind);
dump_localparams_(out, ind);
dump_events_(out, ind);
dump_wires_(out, ind);
if (statement_)
@ -993,11 +1015,11 @@ void PGenerate::dump(ostream&out, unsigned indent) const
out << endl;
for (map<perm_string,PWire*>::const_iterator idx = wires.begin()
; idx != wires.end() ; idx++) {
dump_localparams_(out, indent+2);
(*idx).second->dump(out, indent+2);
}
dump_events_(out, indent+2);
dump_wires_(out, indent+2);
for (list<PGate*>::const_iterator idx = gates.begin()
; idx != gates.end() ; idx++) {
@ -1022,7 +1044,83 @@ void PGenerate::dump(ostream&out, unsigned indent) const
out << setw(indent) << "" << "endgenerate" << endl;
}
void PScope::dump_wires_(ostream&out, unsigned indent) const
void LexicalScope::dump_parameters_(ostream&out, unsigned indent) const
{
typedef map<perm_string,param_expr_t>::const_iterator parm_iter_t;
for (parm_iter_t cur = parameters.begin()
; cur != parameters.end() ; cur ++) {
out << setw(indent) << "" << "parameter "
<< (*cur).second.type << " ";
if ((*cur).second.signed_flag)
out << "signed ";
if ((*cur).second.msb)
out << "[" << *(*cur).second.msb << ":"
<< *(*cur).second.lsb << "] ";
out << (*cur).first << " = ";
if ((*cur).second.expr)
out << *(*cur).second.expr;
else
out << "/* ERROR */";
for (LexicalScope::range_t*tmp = (*cur).second.range
; tmp ; tmp = tmp->next) {
if (tmp->exclude_flag)
out << " exclude ";
else
out << " from ";
if (tmp->low_open_flag)
out << "(";
else
out << "[";
if (tmp->low_expr)
out << *(tmp->low_expr);
else if (tmp->low_open_flag==false)
out << "-inf";
else
out << "<nil>";
out << ":";
if (tmp->high_expr)
out << *(tmp->high_expr);
else if (tmp->high_open_flag==false)
out << "inf";
else
out << "<nil>";
if (tmp->high_open_flag)
out << ")";
else
out << "]";
}
out << ";" << endl;
}
}
void LexicalScope::dump_localparams_(ostream&out, unsigned indent) const
{
typedef map<perm_string,param_expr_t>::const_iterator parm_iter_t;
for (parm_iter_t cur = localparams.begin()
; cur != localparams.end() ; cur ++) {
out << setw(indent) << "" << "localparam ";
if ((*cur).second.msb)
out << "[" << *(*cur).second.msb << ":"
<< *(*cur).second.lsb << "] ";
out << (*cur).first << " = ";
if ((*cur).second.expr)
out << *(*cur).second.expr << ";" << endl;
else
out << "/* ERROR */;" << endl;
}
}
void LexicalScope::dump_events_(ostream&out, unsigned indent) const
{
for (map<perm_string,PEvent*>::const_iterator cur = events.begin()
; cur != events.end() ; cur ++ ) {
PEvent*ev = (*cur).second;
out << setw(indent) << "" << "event " << ev->name() << "; // "
<< ev->get_fileline() << endl;
}
}
void LexicalScope::dump_wires_(ostream&out, unsigned indent) const
{
// Iterate through and display all the wires.
for (map<perm_string,PWire*>::const_iterator wire = wires.begin()
@ -1067,63 +1165,9 @@ void Module::dump(ostream&out) const
out << ")" << endl;
}
typedef map<perm_string,param_expr_t>::const_iterator parm_iter_t;
for (parm_iter_t cur = parameters.begin()
; cur != parameters.end() ; cur ++) {
out << " parameter " << (*cur).second.type << " ";
if ((*cur).second.signed_flag)
out << "signed ";
if ((*cur).second.msb)
out << "[" << *(*cur).second.msb << ":"
<< *(*cur).second.lsb << "] ";
out << (*cur).first << " = ";
if ((*cur).second.expr)
out << *(*cur).second.expr;
else
out << "/* ERROR */";
for (Module::range_t*tmp = (*cur).second.range
; tmp ; tmp = tmp->next) {
if (tmp->exclude_flag)
out << " exclude ";
else
out << " from ";
if (tmp->low_open_flag)
out << "(";
else
out << "[";
if (tmp->low_expr)
out << *(tmp->low_expr);
else if (tmp->low_open_flag==false)
out << "-inf";
else
out << "<nil>";
out << ":";
if (tmp->high_expr)
out << *(tmp->high_expr);
else if (tmp->high_open_flag==false)
out << "inf";
else
out << "<nil>";
if (tmp->high_open_flag)
out << ")";
else
out << "]";
}
out << ";" << endl;
}
dump_parameters_(out, 4);
for (parm_iter_t cur = localparams.begin()
; cur != localparams.end() ; cur ++) {
out << " localparam ";
if ((*cur).second.msb)
out << "[" << *(*cur).second.msb << ":"
<< *(*cur).second.lsb << "] ";
out << (*cur).first << " = ";
if ((*cur).second.expr)
out << *(*cur).second.expr << ";" << endl;
else
out << "/* ERROR */;" << endl;
}
dump_localparams_(out, 4);
typedef map<perm_string,LineInfo*>::const_iterator genvar_iter_t;
for (genvar_iter_t cur = genvars.begin()
@ -1154,12 +1198,7 @@ void Module::dump(ostream&out) const
out << "/* ERROR */;" << endl;
}
for (map<perm_string,PEvent*>::const_iterator cur = events.begin()
; cur != events.end() ; cur ++ ) {
PEvent*ev = (*cur).second;
out << " event " << ev->name() << "; // "
<< ev->get_fileline() << endl;
}
dump_events_(out, 4);
// Iterate through and display all the wires.
dump_wires_(out, 4);

View File

@ -180,7 +180,13 @@ bool NetEBLogic::set_width(unsigned w, bool)
*/
bool NetEBMult::set_width(unsigned w, bool)
{
return w == expr_width();
if (w < left_->expr_width())
left_->set_width(w);
if (w < right_->expr_width())
right_->expr_width();
expr_width(w);
return true;
}
bool NetEBPow::set_width(unsigned w, bool last_chance)

View File

@ -1,7 +1,7 @@
%{
/*
* Copyright (c) 2000-2007 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2008 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -141,7 +141,7 @@ static void make_DFF_CE(Design*des, NetProcTop*top, NetEvWait*wclk,
NetEvProbe*pclk = eclk->probe(0);
NetESignal*d = dynamic_cast<NetESignal*> (asn->rval());
NetNet*ce = cexp? cexp->synthesize(des) : 0;
NetNet*ce = cexp? cexp->synthesize(des, top->scope()) : 0;
if (d == 0) {
cerr << asn->get_fileline() << ": internal error: "

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2000 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2008 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -16,9 +16,6 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: synth.cc,v 1.14 2002/08/12 01:35:00 steve Exp $"
#endif
# include "config.h"
@ -36,12 +33,13 @@
class do_expr : public proc_match_t {
public:
do_expr(Design*d)
: des_(d) { }
do_expr(Design*d, NetScope*s)
: des_(d), scope_(s) { }
private:
Design*des_;
NetScope*scope_;
virtual int assign(NetAssign*);
virtual int assign_nb(NetAssignNB*);
@ -55,7 +53,7 @@ int do_expr::assign(NetAssign*stmt)
if (dynamic_cast<NetESignal*>(stmt->rval()))
return 0;
NetNet*tmp = stmt->rval()->synthesize(des_);
NetNet*tmp = stmt->rval()->synthesize(des_, scope_);
if (tmp == 0)
return 0;
@ -70,7 +68,7 @@ int do_expr::assign_nb(NetAssignNB*stmt)
if (dynamic_cast<NetESignal*>(stmt->rval()))
return 0;
NetNet*tmp = stmt->rval()->synthesize(des_);
NetNet*tmp = stmt->rval()->synthesize(des_, scope_);
if (tmp == 0)
return 0;
@ -84,7 +82,7 @@ int do_expr::condit(NetCondit*stmt)
{
/* synthesize the condition expression, if necessary. */
if (! dynamic_cast<NetESignal*>(stmt->expr())) {
NetNet*tmp = stmt->expr()->synthesize(des_);
NetNet*tmp = stmt->expr()->synthesize(des_, scope_);
if (tmp) {
NetESignal*tmpe = new NetESignal(tmp);
@ -144,13 +142,13 @@ void synth_f::process(class Design*des, class NetProcTop*top)
void synth_f::proc_always_(class Design*des)
{
do_expr expr_pat(des);
do_expr expr_pat(des, top_->scope());
top_->statement()->match_proc(&expr_pat);
}
void synth_f::proc_initial_(class Design*des)
{
do_expr expr_pat(des);
do_expr expr_pat(des, top_->scope());
top_->statement()->match_proc(&expr_pat);
}
@ -159,28 +157,3 @@ void synth(Design*des)
synth_f synth_obj;
des->functor(&synth_obj);
}
/*
* $Log: synth.cc,v $
* Revision 1.14 2002/08/12 01:35:00 steve
* conditional ident string using autoconfig.
*
* Revision 1.13 2002/06/05 03:44:25 steve
* Add support for memory words in l-value of
* non-blocking assignments, and remove the special
* NetAssignMem_ and NetAssignMemNB classes.
*
* Revision 1.12 2001/07/25 03:10:49 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*
* Revision 1.11 2000/11/22 21:18:42 steve
* synthesize the rvalue of <= statements.
*
* Revision 1.10 2000/05/13 20:55:47 steve
* Use yacc based synthesizer.
*
* Revision 1.9 2000/04/16 22:57:34 steve
* Catch expressions that are part of conditionals.
*/

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002-2007 Stephen Williams (steve@icarus.com)
* Copyright (c) 2002-2008 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -60,7 +60,7 @@ bool NetProc::synth_sync(Design*des, NetScope*scope, NetFF*ff,
bool NetAssignBase::synth_async(Design*des, NetScope*scope,
const NetBus&nex_map, NetBus&nex_out)
{
NetNet*rsig = rval_->synthesize(des);
NetNet*rsig = rval_->synthesize(des, scope);
assert(rsig);
NetNet*lsig = lval_->sig();
@ -155,7 +155,7 @@ bool NetCase::synth_async(Design*des, NetScope*scope,
const NetBus&nex_map, NetBus&nex_out)
{
/* Synthesize the select expression. */
NetNet*esig = expr_->synthesize(des);
NetNet*esig = expr_->synthesize(des, scope);
unsigned sel_width = esig->vector_width();
assert(sel_width > 0);

View File

@ -118,6 +118,7 @@ extern "C" const char*ivl_const_bits(ivl_net_const_t net)
assert(net);
switch (net->type) {
case IVL_VT_BOOL:
case IVL_VT_LOGIC:
if (net->width_ <= sizeof(net->b.bit_))
return net->b.bit_;
@ -1912,9 +1913,15 @@ extern "C" ivl_statement_t ivl_stmt_block_stmt(ivl_statement_t net,
extern "C" ivl_scope_t ivl_stmt_call(ivl_statement_t net)
{
switch (net->type_) {
case IVL_ST_ALLOC:
return net->u_.alloc_.scope;
case IVL_ST_DISABLE:
return net->u_.disable_.scope;
case IVL_ST_FREE:
return net->u_.free_.scope;
case IVL_ST_UTASK:
return net->u_.utask_.def;
default:
@ -1972,6 +1979,9 @@ extern "C" ivl_statement_t ivl_stmt_case_stmt(ivl_statement_t net, unsigned idx)
extern "C" ivl_expr_t ivl_stmt_cond_expr(ivl_statement_t net)
{
switch (net->type_) {
case IVL_ST_ASSIGN_NB:
return net->u_.assign_.count;
case IVL_ST_CONDIT:
return net->u_.condit_.cond_;
@ -2034,6 +2044,9 @@ extern "C" uint64_t ivl_stmt_delay_val(ivl_statement_t net)
extern "C" unsigned ivl_stmt_nevent(ivl_statement_t net)
{
switch (net->type_) {
case IVL_ST_ASSIGN_NB:
return net->u_.assign_.nevent;
case IVL_ST_WAIT:
return net->u_.wait_.nevent;
@ -2049,6 +2062,13 @@ extern "C" unsigned ivl_stmt_nevent(ivl_statement_t net)
extern "C" ivl_event_t ivl_stmt_events(ivl_statement_t net, unsigned idx)
{
switch (net->type_) {
case IVL_ST_ASSIGN_NB:
assert(idx < net->u_.assign_.nevent);
if (net->u_.assign_.nevent == 1)
return net->u_.assign_.event;
else
return net->u_.assign_.events[idx];
case IVL_ST_WAIT:
assert(idx < net->u_.wait_.nevent);
if (net->u_.wait_.nevent == 1)
@ -2059,6 +2079,7 @@ extern "C" ivl_event_t ivl_stmt_events(ivl_statement_t net, unsigned idx)
case IVL_ST_TRIGGER:
assert(idx == 0);
return net->u_.wait_.event;
default:
assert(0);
}

View File

@ -59,7 +59,7 @@ bool dll_target::process(const NetProcTop*net)
/* This little bit causes the process to be completely
generated so that it can be passed to the DLL. The
stmt_cur_ member us used to hold a pointer to the current
stmt_cur_ member is used to hold a pointer to the current
statement in progress, and the emit_proc() method fills in
that object.
@ -188,6 +188,16 @@ void dll_target::make_assign_lvals_(const NetAssignBase*net)
}
}
void dll_target::proc_alloc(const NetAlloc*net)
{
assert(stmt_cur_);
assert(stmt_cur_->type_ == IVL_ST_NONE);
FILE_NAME(stmt_cur_, net);
stmt_cur_->type_ = IVL_ST_ALLOC;
stmt_cur_->u_.alloc_.scope = lookup_scope_(net->scope());
}
/*
*/
bool dll_target::proc_assign(const NetAssign*net)
@ -222,6 +232,7 @@ bool dll_target::proc_assign(const NetAssign*net)
void dll_target::proc_assign_nb(const NetAssignNB*net)
{
const NetExpr* delay_exp = net->get_delay();
const NetExpr* cnt_exp = net->get_count();
assert(stmt_cur_);
assert(stmt_cur_->type_ == IVL_ST_NONE);
@ -229,6 +240,8 @@ void dll_target::proc_assign_nb(const NetAssignNB*net)
FILE_NAME(stmt_cur_, net);
stmt_cur_->u_.assign_.delay = 0;
stmt_cur_->u_.assign_.count = 0;
stmt_cur_->u_.assign_.nevent = 0;
/* Make the lval fields. */
make_assign_lvals_(net);
@ -239,6 +252,7 @@ void dll_target::proc_assign_nb(const NetAssignNB*net)
stmt_cur_->u_.assign_.rval_ = expr_;
expr_ = 0;
/* Process a delay if it exists. */
if (const NetEConst*delay_num = dynamic_cast<const NetEConst*>(delay_exp)) {
verinum val = delay_num->value();
ivl_expr_t de = new struct ivl_expr_s;
@ -253,6 +267,96 @@ void dll_target::proc_assign_nb(const NetAssignNB*net)
stmt_cur_->u_.assign_.delay = expr_;
expr_ = 0;
}
/* Process a count if it exists. */
if (const NetEConst*cnt_num = dynamic_cast<const NetEConst*>(cnt_exp)) {
verinum val = cnt_num->value();
ivl_expr_t cnt = new struct ivl_expr_s;
cnt->type_ = IVL_EX_ULONG;
cnt->width_ = 8 * sizeof(unsigned long);
cnt->signed_ = 0;
cnt->u_.ulong_.value = val.as_ulong();
stmt_cur_->u_.assign_.count = cnt;
} else if (cnt_exp != 0) {
cnt_exp->expr_scan(this);
stmt_cur_->u_.assign_.count = expr_;
expr_ = 0;
}
/* Process the events if they exist. This is a copy of code
* from NetEvWait below. */
if (net->nevents() > 0) {
stmt_cur_->u_.assign_.nevent = net->nevents();
if (net->nevents() > 1) {
stmt_cur_->u_.assign_.events = (ivl_event_t*)
calloc(net->nevents(), sizeof(ivl_event_t*));
}
for (unsigned edx = 0 ; edx < net->nevents() ; edx += 1) {
/* Locate the event by name. Save the ivl_event_t in the
statement so that the generator can find it easily. */
const NetEvent*ev = net->event(edx);
ivl_scope_t ev_scope = lookup_scope_(ev->scope());
ivl_event_t ev_tmp=0;
assert(ev_scope);
assert(ev_scope->nevent_ > 0);
for (unsigned idx = 0; idx < ev_scope->nevent_; idx += 1) {
const char*ename =
ivl_event_basename(ev_scope->event_[idx]);
if (strcmp(ev->name(), ename) == 0) {
ev_tmp = ev_scope->event_[idx];
break;
}
}
// XXX should we assert(ev_tmp)?
if (net->nevents() == 1)
stmt_cur_->u_.assign_.event = ev_tmp;
else
stmt_cur_->u_.assign_.events[edx] = ev_tmp;
/* If this is an event with a probe, then connect up the
pins. This wasn't done during the ::event method because
the signals weren't scanned yet. */
if (ev->nprobe() >= 1) {
unsigned iany = 0;
unsigned ineg = ev_tmp->nany;
unsigned ipos = ineg + ev_tmp->nneg;
for (unsigned idx = 0; idx < ev->nprobe(); idx += 1) {
const NetEvProbe*pr = ev->probe(idx);
unsigned base = 0;
switch (pr->edge()) {
case NetEvProbe::ANYEDGE:
base = iany;
iany += pr->pin_count();
break;
case NetEvProbe::NEGEDGE:
base = ineg;
ineg += pr->pin_count();
break;
case NetEvProbe::POSEDGE:
base = ipos;
ipos += pr->pin_count();
break;
}
for (unsigned bit = 0; bit < pr->pin_count();
bit += 1) {
ivl_nexus_t nex = (ivl_nexus_t)
pr->pin(bit).nexus()->t_cookie();
assert(nex);
ev_tmp->pins[base+bit] = nex;
}
}
}
}
}
}
bool dll_target::proc_block(const NetBlock*net)
@ -535,6 +639,16 @@ void dll_target::proc_forever(const NetForever*net)
stmt_cur_ = save_cur_;
}
void dll_target::proc_free(const NetFree*net)
{
assert(stmt_cur_);
assert(stmt_cur_->type_ == IVL_ST_NONE);
FILE_NAME(stmt_cur_, net);
stmt_cur_->type_ = IVL_ST_FREE;
stmt_cur_->u_.free_.scope = lookup_scope_(net->scope());
}
bool dll_target::proc_release(const NetRelease*net)
{
assert(stmt_cur_);
@ -643,6 +757,7 @@ bool dll_target::proc_wait(const NetEvWait*net)
stmt_cur_->u_.wait_.stmt_ = (struct ivl_statement_s*)
calloc(1, sizeof(struct ivl_statement_s));
// This event processing code is also in the NB assign above.
stmt_cur_->u_.wait_.nevent = net->nevents();
if (net->nevents() > 1) {
stmt_cur_->u_.wait_.events = (ivl_event_t*)

View File

@ -32,6 +32,8 @@
# include <stdlib.h>
# include "ivl_assert.h"
struct dll_target dll_target_obj;
#if defined(__WIN32__)
inline ivl_dll_t ivl_dlopen(const char *name)
@ -144,8 +146,6 @@ static perm_string make_scope_name(const hname_t&name)
return lex_strings.make(buf);
}
static struct dll_target dll_target_obj;
static void drive_from_link(const Link&lnk, ivl_drive_t&drv0, ivl_drive_t&drv1)
{
switch (lnk.drive0()) {
@ -2199,7 +2199,7 @@ bool dll_target::net_const(const NetConst*net)
struct ivl_net_const_s *obj = new struct ivl_net_const_s;
obj->type = IVL_VT_LOGIC;
obj->type = IVL_VT_BOOL;
/* constants have a single vector output. */
assert(net->pin_count() == 1);
@ -2223,9 +2223,13 @@ bool dll_target::net_const(const NetConst*net)
bits[idx] = '1';
break;
case verinum::Vx:
if (obj->type == IVL_VT_BOOL)
obj->type = IVL_VT_LOGIC;
bits[idx] = 'x';
break;
case verinum::Vz:
if (obj->type == IVL_VT_BOOL)
obj->type = IVL_VT_LOGIC;
bits[idx] = 'z';
break;
}
@ -2579,4 +2583,38 @@ bool dll_target::signal_paths(const NetNet*net)
return true;
}
extern const struct target tgt_dll = { "dll", &dll_target_obj };
void dll_target::test_version(const char*target_name)
{
dll_ = ivl_dlopen(target_name);
if ((dll_ == 0) && (target_name[0] != '/')) {
size_t len = strlen(basedir) + 1 + strlen(target_name) + 1;
char*tmp = new char[len];
sprintf(tmp, "%s/%s", basedir, target_name);
dll_ = ivl_dlopen(tmp);
delete[]tmp;
}
if (dll_ == 0) {
cout << "\n\nUnable to load " << target_name
<< " for version details." << endl;
return;
}
target_query_f target_query = (target_query_f)ivl_dlsym(dll_, LU "target_query" TU);
if (target_query == 0) {
cerr << "Target " << target_name
<< " has no version hooks." << endl;
return;
}
const char*version_string = (*target_query) ("version");
if (version_string == 0) {
cerr << "Target " << target_name
<< " has no version string" << endl;
return;
}
cout << target_name << ": " << version_string << endl;
}

23
t-dll.h
View File

@ -63,6 +63,10 @@ struct ivl_design_s {
*/
struct dll_target : public target_t, public expr_scan_t {
// This is a special function for loading and testing the
// version of a loadable target code generator.
void test_version(const char*target_name);
bool start_design(const Design*);
int end_design(const Design*);
@ -111,6 +115,7 @@ struct dll_target : public target_t, public expr_scan_t {
/* These methods and members are used for forming the
statements of a thread. */
struct ivl_statement_s*stmt_cur_;
void proc_alloc(const NetAlloc*);
bool proc_assign(const NetAssign*);
void proc_assign_nb(const NetAssignNB*);
bool proc_block(const NetBlock*);
@ -122,6 +127,7 @@ struct dll_target : public target_t, public expr_scan_t {
bool proc_disable(const NetDisable*);
bool proc_force(const NetForce*);
void proc_forever(const NetForever*);
void proc_free(const NetFree*);
bool proc_release(const NetRelease*);
void proc_repeat(const NetRepeat*);
void proc_stask(const NetSTask*);
@ -178,6 +184,8 @@ struct dll_target : public target_t, public expr_scan_t {
static ivl_expr_t expr_from_value_(const verinum&that);
};
extern struct dll_target dll_target_obj;
/*
* These are various private declarations used by the t-dll target.
*/
@ -659,12 +667,23 @@ struct ivl_statement_s {
unsigned lineno;
union {
struct { /* IVL_ST_ALLOC */
ivl_scope_t scope;
} alloc_;
struct { /* IVL_ST_ASSIGN IVL_ST_ASSIGN_NB
IVL_ST_CASSIGN, IVL_ST_DEASSIGN */
unsigned lvals_;
struct ivl_lval_s*lval_;
ivl_expr_t rval_;
ivl_expr_t delay;
// The following are only for NB event control.
ivl_expr_t count;
unsigned nevent;
union {
ivl_event_t event;
ivl_event_t*events;
};
} assign_;
struct { /* IVL_ST_BLOCK, IVL_ST_FORK */
@ -705,6 +724,10 @@ struct ivl_statement_s {
ivl_statement_t stmt_;
} forever_;
struct { /* IVL_ST_FREE */
ivl_scope_t scope;
} free_;
struct { /* IVL_ST_STASK */
const char*name_;
unsigned nparm_;

View File

@ -243,6 +243,12 @@ bool target_t::process(const NetProcTop*top)
return top->statement()->emit_proc(this);
}
void target_t::proc_alloc(const NetAlloc*)
{
cerr << "target (" << typeid(*this).name() << "): "
"Unhandled proc_alloc." << endl;
}
bool target_t::proc_assign(const NetAssign*)
{
cerr << "target (" << typeid(*this).name() << "): "
@ -322,6 +328,12 @@ void target_t::proc_forever(const NetForever*)
"Unhandled proc_forever." << endl;
}
void target_t::proc_free(const NetFree*)
{
cerr << "target (" << typeid(*this).name() << "): "
"Unhandled proc_free." << endl;
}
bool target_t::proc_release(const NetRelease*dev)
{
cerr << dev->get_fileline() << ": internal error: "

View File

@ -105,6 +105,7 @@ struct target_t {
virtual bool process(const NetProcTop*);
/* Various kinds of process nodes are dispatched through these. */
virtual void proc_alloc(const NetAlloc*);
virtual bool proc_assign(const NetAssign*);
virtual void proc_assign_nb(const NetAssignNB*);
virtual bool proc_block(const NetBlock*);
@ -116,6 +117,7 @@ struct target_t {
virtual bool proc_disable(const NetDisable*);
virtual bool proc_force(const NetForce*);
virtual void proc_forever(const NetForever*);
virtual void proc_free(const NetFree*);
virtual bool proc_release(const NetRelease*);
virtual void proc_repeat(const NetRepeat*);
virtual bool proc_trigger(const NetEvTrig*);
@ -151,11 +153,6 @@ struct expr_scan_t {
};
/* The emit functions take a design and emit it to the output stream
using the specified target. If the target is given by name, it is
located in the target_table and used. */
extern int emit(const Design*des, const char*type);
/* This function takes a fully qualified Verilog name (which may have,
for example, dots in it) and produces a mangled version that can be
used by most any language. */
@ -165,8 +162,4 @@ extern string mangle(const string&str);
used inside a string constant for a C++ compiler. */
extern string stresc(const string&str);
/* This is the table of supported output targets. It is a null
terminated array of pointers to targets. */
extern const struct target *target_table[];
#endif

View File

@ -1,29 +0,0 @@
/*
* Copyright (c) 1998 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
# include "config.h"
# include "target.h"
extern const struct target tgt_dll;
const struct target *target_table[] = {
&tgt_dll,
0
};

View File

@ -35,7 +35,7 @@ INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
CPPFLAGS = @ident_support@ -I.. -I$(srcdir)/.. -I$(srcdir) @CPPFLAGS@ @DEFS@ @PICFLAG@
CPPFLAGS = @ident_support@ -I.. -I$(srcdir)/.. -I$(srcdir) -DVERSION='"$(VERSION)"' @CPPFLAGS@ @DEFS@ @PICFLAG@
CFLAGS = -Wall @CFLAGS@
LDFLAGS = @LDFLAGS@

View File

@ -1,5 +1,4 @@
functor:synth2
functor:synth
functor:syn-rules
-t:dll
flag:DLL=null.tgt

View File

@ -16,11 +16,9 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: null.c,v 1.7 2002/08/12 01:35:03 steve Exp $"
#endif
# include "config.h"
# include <string.h>
/*
* This is a null target module. It does nothing.
@ -28,35 +26,34 @@
# include "ivl_target.h"
static const char*version_string =
"Icarus Verilog NULL Code Generator " VERSION "\n"
" This program is free software; you can redistribute it and/or modify\n"
" it under the terms of the GNU General Public License as published by\n"
" the Free Software Foundation; either version 2 of the License, or\n"
" (at your option) any later version.\n"
"\n"
" This program is distributed in the hope that it will be useful,\n"
" but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
" GNU General Public License for more details.\n"
"\n"
" You should have received a copy of the GNU General Public License\n"
" along with this program; if not, write to the Free Software\n"
" Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA\n"
;
int target_design(ivl_design_t des)
{
return 0;
}
/*
* $Log: null.c,v $
* Revision 1.7 2002/08/12 01:35:03 steve
* conditional ident string using autoconfig.
*
* Revision 1.6 2001/09/30 16:45:10 steve
* Fix some Cygwin DLL handling. (Venkat Iyer)
*
* Revision 1.5 2001/07/25 03:10:50 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*
* Revision 1.4 2001/05/22 02:14:47 steve
* Update the mingw build to not require cygwin files.
*
* Revision 1.3 2001/05/20 15:09:40 steve
* Mingw32 support (Venkat Iyer)
*
* Revision 1.2 2001/02/07 22:21:59 steve
* ivl_target header search path fixes.
*
* Revision 1.1 2000/12/02 04:50:32 steve
* Make the null target into a loadable target.
*
*/
const char* target_query(const char*key)
{
if (strcmp(key,"version") == 0)
return version_string;
return 0;
}

View File

@ -1,2 +1 @@
-t:dll
flag:DLL=null.tgt

View File

@ -35,7 +35,7 @@ INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
CPPFLAGS = @ident_support@ -I.. -I$(srcdir)/.. @CPPFLAGS@ @DEFS@ @PICFLAG@
CPPFLAGS = @ident_support@ -I.. -I$(srcdir)/.. -DVERSION='"$(VERSION)"' @CPPFLAGS@ @DEFS@ @PICFLAG@
CFLAGS = -Wall @CFLAGS@
LDFLAGS = @LDFLAGS@

View File

@ -81,16 +81,28 @@ static void show_binary_expression(ivl_expr_t net, unsigned ind)
switch (ivl_expr_opcode(net)) {
case '*':
/* The width of multiply expressions is the sum of the
widths of the operands. This is slightly different
from the way the Verilog standard does it, but allows
us to keep operands smaller. */
width = ivl_expr_width(ivl_expr_oper1(net));
width += ivl_expr_width(ivl_expr_oper2(net));
if (ivl_expr_width(net) != width) {
fprintf(out, "%*sERROR: Result width incorrect. Expecting %u, got %u\n",
ind+3, "", width, ivl_expr_width(net));
stub_errors += 1;
if (ivl_expr_value(net) == IVL_VT_REAL) {
if (ivl_expr_width(net) != 1) {
fprintf(out, "%*sERROR: Result width incorrect. Expecting 1, got %u\n",
ind+3, "", ivl_expr_width(net));
stub_errors += 1;
}
} else {
/* The width of a multiply may be any width. The
implicit assumption is that the multiply
returns a width that is the sum of the widths
of the arguments, that is then truncated to the
desired width, never padded. The compiler will
automatically take care of sign extensions of
arguments, so that the code generator need only
generate an UNSIGNED multiply, and the result
will come out right. */
unsigned max_width = ivl_expr_width(oper1) + ivl_expr_width(oper2);
if (ivl_expr_width(net) > max_width) {
fprintf(out, "%*sERROR: Result width to width. Expecting <= %u, got %u\n",
ind+3, "", max_width, ivl_expr_width(net));
stub_errors += 1;
}
}
break;

View File

@ -183,6 +183,10 @@ void show_statement(ivl_statement_t net, unsigned ind)
switch (code) {
case IVL_ST_ALLOC:
fprintf(out, "%*sallocate automatic storage ...\n", ind, "");
break;
case IVL_ST_ASSIGN:
fprintf(out, "%*sASSIGN <lwidth=%u>\n", ind, "",
ivl_stmt_lwidth(net));
@ -316,6 +320,10 @@ void show_statement(ivl_statement_t net, unsigned ind)
break;
}
case IVL_ST_FREE:
fprintf(out, "%*sfree automatic storage ...\n", ind, "");
break;
case IVL_ST_NOOP:
fprintf(out, "%*s/* noop */;\n", ind, "");
break;
@ -356,4 +364,3 @@ void show_statement(ivl_statement_t net, unsigned ind)
fprintf(out, "%*sunknown statement type (%u)\n", ind, "", code);
}
}

View File

@ -3,5 +3,4 @@ functor:synth
functor:syn-rules
functor:cprop
functor:nodangle
-t:dll
flag:DLL=stub.tgt

View File

@ -28,8 +28,26 @@
# include "priv.h"
# include <stdlib.h>
# include <inttypes.h>
# include <string.h>
# include <assert.h>
static const char*version_string =
"Icarus Verilog Stub Target " VERSION "\n"
" This program is free software; you can redistribute it and/or modify\n"
" it under the terms of the GNU General Public License as published by\n"
" the Free Software Foundation; either version 2 of the License, or\n"
" (at your option) any later version.\n"
"\n"
" This program is distributed in the hope that it will be useful,\n"
" but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
" GNU General Public License for more details.\n"
"\n"
" You should have received a copy of the GNU General Public License\n"
" along with this program; if not, write to the Free Software\n"
" Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA\n"
;
FILE*out;
int stub_errors = 0;
@ -131,6 +149,26 @@ const char*data_type_string(ivl_variable_type_t vtype)
return vt;
}
/*
* The compiler will check the types of drivers to signals and will
* only connect outputs to signals that are compatible. This function
* shows the type compatibility that the compiler enforces at the
* ivl_target.h level.
*/
static int check_signal_drive_type(ivl_variable_type_t sig_type,
ivl_variable_type_t driver_type)
{
if (sig_type == IVL_VT_LOGIC && driver_type == IVL_VT_BOOL)
return !0;
if (sig_type == IVL_VT_LOGIC && driver_type == IVL_VT_LOGIC)
return !0;
if (sig_type == IVL_VT_BOOL && driver_type == IVL_VT_BOOL)
return !0;
if (sig_type == driver_type)
return !0;
return 0;
}
/*
* The compare-like LPM nodes have input widths that match the
* ivl_lpm_width() value, and an output width of 1. This function
@ -178,11 +216,11 @@ static void show_lpm_arithmetic_pins(ivl_lpm_t net)
static void show_lpm_abs(ivl_lpm_t net)
{
unsigned width = ivl_lpm_width(net);
ivl_nexus_t nex;
fprintf(out, " LPM_ABS %s: <width=%u>\n",
ivl_lpm_basename(net), width);
ivl_nexus_t nex;
nex = ivl_lpm_q(net, 0);
fprintf(out, " Q: %s\n", ivl_nexus_name(ivl_lpm_q(net, 0)));
@ -243,12 +281,13 @@ static void show_lpm_array(ivl_lpm_t net)
static void show_lpm_cast_int(ivl_lpm_t net)
{
unsigned width = ivl_lpm_width(net);
ivl_nexus_t q, a;
fprintf(out, " LPM_CAST_INT %s: <width=%u>\n",
ivl_lpm_basename(net), width);
ivl_nexus_t q = ivl_lpm_q(net,0);
ivl_nexus_t a = ivl_lpm_data(net,0);
q = ivl_lpm_q(net,0);
a = ivl_lpm_data(net,0);
fprintf(out, " O: %s\n", ivl_nexus_name(ivl_lpm_q(net,0)));
fprintf(out, " A: %s\n", ivl_nexus_name(ivl_lpm_data(net,0)));
@ -268,12 +307,13 @@ static void show_lpm_cast_int(ivl_lpm_t net)
static void show_lpm_cast_real(ivl_lpm_t net)
{
unsigned width = ivl_lpm_width(net);
ivl_nexus_t q, a;
fprintf(out, " LPM_CAST_REAL %s: <width=%u>\n",
ivl_lpm_basename(net), width);
ivl_nexus_t q = ivl_lpm_q(net,0);
ivl_nexus_t a = ivl_lpm_data(net,0);
q = ivl_lpm_q(net,0);
a = ivl_lpm_data(net,0);
fprintf(out, " O: %s\n", ivl_nexus_name(ivl_lpm_q(net,0)));
fprintf(out, " A: %s\n", ivl_nexus_name(ivl_lpm_data(net,0)));
@ -1040,15 +1080,17 @@ static void signal_nexus_const(ivl_signal_t sig,
fprintf(out, " const-");
switch (ivl_const_type(con)) {
case IVL_VT_BOOL:
case IVL_VT_LOGIC:
bits = ivl_const_bits(con);
assert(bits);
for (idx = 0 ; idx < width ; idx += 1) {
fprintf(out, "%c", bits[width-idx-1]);
}
break;
case IVL_VT_REAL:
fprintf(out, "%lf", ivl_const_real(con));
fprintf(out, "%f", ivl_const_real(con));
break;
default:
@ -1064,7 +1106,10 @@ static void signal_nexus_const(ivl_signal_t sig,
stub_errors += 1;
}
if (ivl_signal_data_type(sig) != ivl_const_type(con)) {
int drive_type_ok = check_signal_drive_type(ivl_signal_data_type(sig),
ivl_const_type(con));
if (! drive_type_ok) {
fprintf(out, "ERROR: Signal data type does not match"
" literal type.\n");
stub_errors += 1;
@ -1443,12 +1488,13 @@ static void show_logic(ivl_net_logic_t net)
static int show_scope(ivl_scope_t net, void*x)
{
unsigned idx;
char *is_auto;
fprintf(out, "scope: %s (%u parameters, %u signals, %u logic)",
ivl_scope_name(net), ivl_scope_params(net),
ivl_scope_sigs(net), ivl_scope_logs(net));
char *is_auto = ivl_scope_is_auto(net) ? "automatic " : "";
is_auto = ivl_scope_is_auto(net) ? "automatic " : "";
switch (ivl_scope_type(net)) {
case IVL_SCT_MODULE:
fprintf(out, " module %s", ivl_scope_tname(net));
@ -1608,3 +1654,11 @@ int target_design(ivl_design_t des)
return stub_errors;
}
const char* target_query(const char*key)
{
if (strcmp(key,"version") == 0)
return version_string;
return 0;
}

View File

@ -1,4 +1,3 @@
functor:cprop
functor:nodangle
-t:dll
flag:DLL=stub.tgt

View File

@ -28,6 +28,9 @@ void show_switch(ivl_switch_t net)
{
const char*name = ivl_switch_basename(net);
int has_enable = 0;
ivl_nexus_t nexa, nexb;
ivl_variable_type_t nex_type_a, nex_type_b;
const char*nex_name;
switch (ivl_switch_type(net)) {
case IVL_SW_TRAN:
@ -61,14 +64,14 @@ void show_switch(ivl_switch_t net)
fprintf(out, " island=%p\n", ivl_switch_island(net));
ivl_nexus_t nexa = ivl_switch_a(net);
const char*nex_name = nexa? ivl_nexus_name(nexa) : "";
ivl_variable_type_t nex_type_a = nexa? type_of_nexus(nexa) : IVL_VT_NO_TYPE;
nexa = ivl_switch_a(net);
nex_name = nexa? ivl_nexus_name(nexa) : "";
nex_type_a = nexa? type_of_nexus(nexa) : IVL_VT_NO_TYPE;
fprintf(out, " A: %s <type=%s>\n", nex_name, data_type_string(nex_type_a));
ivl_nexus_t nexb = ivl_switch_b(net);
nexb = ivl_switch_b(net);
nex_name = nexb? ivl_nexus_name(nexb) : "";
ivl_variable_type_t nex_type_b = nexb? type_of_nexus(nexb) : IVL_VT_NO_TYPE;
nex_type_b = nexb? type_of_nexus(nexb) : IVL_VT_NO_TYPE;
fprintf(out, " B: %s <type=%s>\n", nex_name, data_type_string(nex_type_b));
/* The A/B pins of the switch must be present, and must match. */

View File

@ -47,7 +47,7 @@ static vhdl_expr *inputs_to_expr(vhdl_scope *scope, vhdl_binop_t op,
}
/*
* Convert a gate intput to an unary expression.
* Convert a gate input to an unary expression.
*/
static vhdl_expr *input_to_expr(vhdl_scope *scope, vhdl_unaryop_t op,
ivl_net_logic_t log)

View File

@ -34,7 +34,7 @@
* successfully.
*
* An alternative is to use the VHPI interface supported by
* some VHDL simulators and implement the $finish funcitonality
* some VHDL simulators and implement the $finish functionality
* in C. This function can be enabled with the flag
* -puse-vhpi-finish=1.
*/
@ -232,7 +232,7 @@ void make_assignment(vhdl_procedural *proc, stmt_container *container,
// performed on assignments of constant values to prevent
// ordering problems.
// This also has another application: If this is an `inital'
// This also has another application: If this is an `initial'
// process and we haven't yet generated a `wait' statement then
// moving the assignment to the initialization preserves the
// expected Verilog behaviour: VHDL does not distinguish
@ -628,7 +628,7 @@ int draw_utask(vhdl_procedural *proc, stmt_container *container,
// TODO: adding some comments to the output would be helpful
// TOOD: this completely ignores paremeters!
// TOOD: this completely ignores parameters!
draw_stmt(proc, container, ivl_scope_def(tscope), false);
return 0;

View File

@ -97,7 +97,7 @@ bool seen_signal_before(ivl_signal_t sig)
}
/*
* Remeber the association of signal to entity.
* Remember the association of signal to entity.
*/
void remember_signal(ivl_signal_t sig, vhdl_scope *scope)
{

View File

@ -1,4 +1,3 @@
functor:cprop
functor:nodangle
-t:dll
flag:DLL=vhdl.tgt

View File

@ -856,7 +856,7 @@ vhdl_function::vhdl_function(const char *name, vhdl_type *ret_type)
: vhdl_decl(name, ret_type)
{
// A function contains two scopes:
// scope_ = The paramters
// scope_ = The parameters
// variables_ = Local variables
// A call to get_scope returns variables_ whose parent is scope_
variables_.set_parent(&scope_);

View File

@ -38,7 +38,7 @@ INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
CPPFLAGS = @ident_support@ -I. -I$(srcdir)/.. @CPPFLAGS@ @DEFS@ @PICFLAG@
CPPFLAGS = @ident_support@ -I. -I$(srcdir)/.. -DVERSION='"$(VERSION)"' @CPPFLAGS@ @DEFS@ @PICFLAG@
CFLAGS = -Wall @CFLAGS@
LDFLAGS = @LDFLAGS@

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002 Stephen Williams (steve@icarus.com)
* Copyright (c) 2002-2008 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -16,9 +16,6 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: draw_mux.c,v 1.14 2007/01/16 05:44:16 steve Exp $"
#endif
# include "vvp_priv.h"
# include <assert.h>
@ -36,28 +33,50 @@
static void draw_lpm_mux_ab(ivl_lpm_t net, const char*muxz)
{
unsigned width = ivl_lpm_width(net);
ivl_expr_t d_rise, d_fall, d_decay;
const char*dly;
const char* input[3];
/* Only support A-B muxes in this function. */
assert(ivl_lpm_size(net) == 2);
assert(ivl_lpm_selects(net) == 1);
ivl_expr_t d_rise = ivl_lpm_delay(net, 0);
ivl_expr_t d_fall = ivl_lpm_delay(net, 1);
ivl_expr_t d_decay = ivl_lpm_delay(net, 2);
d_rise = ivl_lpm_delay(net, 0);
d_fall = ivl_lpm_delay(net, 1);
d_decay = ivl_lpm_delay(net, 2);
const char*dly = "";
dly = "";
if (d_rise != 0) {
assert(number_is_immediate(d_rise, 64, 0));
assert(number_is_immediate(d_fall, 64, 0));
assert(number_is_immediate(d_decay, 64, 0));
dly = "/d";
fprintf(vvp_out, "L_%p .delay (%lu,%lu,%lu) L_%p/d;\n",
net, get_number_immediate(d_rise),
get_number_immediate(d_rise),
get_number_immediate(d_rise), net);
if (number_is_immediate(d_rise, 64, 0) &&
number_is_immediate(d_fall, 64, 0) &&
number_is_immediate(d_decay, 64, 0)) {
fprintf(vvp_out, "L_%p .delay (%lu,%lu,%lu) L_%p/d;\n",
net, get_number_immediate(d_rise),
get_number_immediate(d_rise),
get_number_immediate(d_rise), net);
} else {
ivl_signal_t sig;
assert(ivl_expr_type(d_rise) == IVL_EX_SIGNAL);
assert(ivl_expr_type(d_fall) == IVL_EX_SIGNAL);
assert(ivl_expr_type(d_decay) == IVL_EX_SIGNAL);
fprintf(vvp_out, "L_%p .delay L_%p/d", net, net);
sig = ivl_expr_signal(d_rise);
assert(ivl_signal_dimensions(sig) == 0);
fprintf(vvp_out, ", v%p_0", sig);
sig = ivl_expr_signal(d_fall);
assert(ivl_signal_dimensions(sig) == 0);
fprintf(vvp_out, ", v%p_0", sig);
sig = ivl_expr_signal(d_decay);
assert(ivl_signal_dimensions(sig) == 0);
fprintf(vvp_out, ", v%p_0;\n", sig);
}
}
const char* input[3];
input[0] = draw_net_input(ivl_lpm_data(net,0));
input[1] = draw_net_input(ivl_lpm_data(net,1));
input[2] = draw_net_input(ivl_lpm_select(net));
@ -144,48 +163,3 @@ void draw_lpm_mux(ivl_lpm_t net)
devices to handle the arbitrary size. */
draw_lpm_mux_nest(net, muxz);
}
/*
* $Log: draw_mux.c,v $
* Revision 1.14 2007/01/16 05:44:16 steve
* Major rework of array handling. Memories are replaced with the
* more general concept of arrays. The NetMemory and NetEMemory
* classes are removed from the ivl core program, and the IVL_LPM_RAM
* lpm type is removed from the ivl_target API.
*
* Revision 1.13 2005/10/12 17:26:17 steve
* MUX nodes get inputs from nets, not from net inputs,
* Detect and draw alias nodes to reduce net size and
* handle force confusion.
*
* Revision 1.12 2005/09/01 04:11:37 steve
* Generate code to handle real valued muxes.
*
* Revision 1.11 2005/08/27 04:32:08 steve
* Handle synthesis of fully packed case statements.
*
* Revision 1.10 2005/06/17 03:46:52 steve
* Make functors know their own width.
*
* Revision 1.9 2005/04/06 05:29:09 steve
* Rework NetRamDq and IVL_LPM_RAM nodes.
*
* Revision 1.8 2005/02/12 22:54:29 steve
* Implement a-b muxes as vector devices
*
* Revision 1.7 2003/12/19 01:27:10 steve
* Fix various unsigned compare warnings.
*
* Revision 1.6 2003/02/25 03:40:45 steve
* Eliminate use of ivl_lpm_name function.
*
* Revision 1.5 2002/08/29 03:04:01 steve
* Generate x out for x select on wide muxes.
*
* Revision 1.4 2002/08/12 01:35:03 steve
* conditional ident string using autoconfig.
*
* Revision 1.3 2002/08/11 23:47:04 steve
* Add missing Log and Ident strings.
*
*/

View File

@ -146,12 +146,14 @@ static struct vvp_nexus_data*new_nexus_data()
static int nexus_drive_is_strength_aware(ivl_nexus_ptr_t nptr)
{
ivl_net_logic_t log;
if (ivl_nexus_ptr_drive0(nptr) != IVL_DR_STRONG)
return 1;
if (ivl_nexus_ptr_drive1(nptr) != IVL_DR_STRONG)
return 1;
ivl_net_logic_t log = ivl_nexus_ptr_log(nptr);
log = ivl_nexus_ptr_log(nptr);
if (log != 0) {
/* These logic gates are able to generate unusual
strength values and so their outputs are considered
@ -325,9 +327,11 @@ static char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr)
cptr = ivl_nexus_ptr_con(nptr);
if (cptr) {
char *result = 0;
ivl_expr_t d_rise, d_fall, d_decay;
/* Constants should have exactly 1 pin, with a literal value. */
assert(nptr_pin == 0);
char *result = 0;
switch (ivl_const_type(cptr)) {
case IVL_VT_LOGIC:
@ -353,26 +357,48 @@ static char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr)
break;
}
ivl_expr_t d_rise = ivl_const_delay(cptr, 0);
ivl_expr_t d_fall = ivl_const_delay(cptr, 1);
ivl_expr_t d_decay = ivl_const_delay(cptr, 2);
d_rise = ivl_const_delay(cptr, 0);
d_fall = ivl_const_delay(cptr, 1);
d_decay = ivl_const_delay(cptr, 2);
/* We have a delayed constant, so we need to build some code. */
if (d_rise != 0) {
assert(number_is_immediate(d_rise, 64, 0));
assert(number_is_immediate(d_fall, 64, 0));
assert(number_is_immediate(d_decay, 64, 0));
fprintf(vvp_out, "L_%p/d .functor BUFZ 1, %s, "
"C4<0>, C4<0>, C4<0>;\n", cptr, result);
fprintf(vvp_out, "L_%p .delay (%lu,%lu,%lu) L_%p/d;\n",
cptr, get_number_immediate(d_rise),
get_number_immediate(d_rise),
get_number_immediate(d_rise), cptr);
free(result);
char tmp[128];
fprintf(vvp_out, "L_%p/d .functor BUFZ 1, %s, "
"C4<0>, C4<0>, C4<0>;\n", cptr, result);
free(result);
/* Is this a fixed or variable delay? */
if (number_is_immediate(d_rise, 64, 0) &&
number_is_immediate(d_fall, 64, 0) &&
number_is_immediate(d_decay, 64, 0)) {
fprintf(vvp_out, "L_%p .delay (%lu,%lu,%lu) L_%p/d;\n",
cptr, get_number_immediate(d_rise),
get_number_immediate(d_rise),
get_number_immediate(d_rise), cptr);
} else {
ivl_signal_t sig;
assert(ivl_expr_type(d_rise) == IVL_EX_SIGNAL);
assert(ivl_expr_type(d_fall) == IVL_EX_SIGNAL);
assert(ivl_expr_type(d_decay) == IVL_EX_SIGNAL);
fprintf(vvp_out, "L_%p .delay L_%p/d", cptr, cptr);
sig = ivl_expr_signal(d_rise);
assert(ivl_signal_dimensions(sig) == 0);
fprintf(vvp_out, ", v%p_0", sig);
sig = ivl_expr_signal(d_fall);
assert(ivl_signal_dimensions(sig) == 0);
fprintf(vvp_out, ", v%p_0", sig);
sig = ivl_expr_signal(d_decay);
assert(ivl_signal_dimensions(sig) == 0);
fprintf(vvp_out, ", v%p_0;\n", sig);
}
snprintf(tmp, sizeof tmp, "L_%p", cptr);
result = strdup(tmp);
}
@ -686,4 +712,3 @@ const char*draw_net_input(ivl_nexus_t nex)
return nex_data->net_input;
}

View File

@ -33,20 +33,24 @@ static void draw_tran_island(ivl_island_t island)
void draw_switch_in_scope(ivl_switch_t sw)
{
ivl_island_t island = ivl_switch_island(sw);
ivl_island_t island;
ivl_nexus_t nex_a, nex_b, enable;
const char*str_a, *str_b, *str_e;
island = ivl_switch_island(sw);
if (ivl_island_flag_test(island, 0) == 0)
draw_tran_island(island);
ivl_nexus_t nex_a = ivl_switch_a(sw);
nex_a = ivl_switch_a(sw);
assert(nex_a);
const char*str_a = draw_net_input(nex_a);
str_a = draw_net_input(nex_a);
ivl_nexus_t nex_b = ivl_switch_b(sw);
nex_b = ivl_switch_b(sw);
assert(nex_b);
const char*str_b = draw_net_input(nex_b);
str_b = draw_net_input(nex_b);
ivl_nexus_t enable = ivl_switch_enable(sw);
const char*str_e = 0;
enable = ivl_switch_enable(sw);
str_e = 0;
if (enable)
str_e = draw_net_input(enable);

View File

@ -28,13 +28,14 @@
static void function_argument_logic(ivl_signal_t port, ivl_expr_t exp)
{
struct vector_info res;
unsigned pwidth;
/* ports cannot be arrays. */
assert(ivl_signal_dimensions(port) == 0);
res = draw_eval_expr_wid(exp, ivl_signal_width(port), 0);
/* We could have extra bits so only select the ones we need. */
unsigned pwidth = ivl_signal_width(port);
pwidth = ivl_signal_width(port);
fprintf(vvp_out, " %%set/v v%p_0, %u, %u;\n", port, res.base,
(res.wid > pwidth) ? pwidth : res.wid);
@ -87,6 +88,12 @@ struct vector_info draw_ufunc_expr(ivl_expr_t exp, unsigned wid)
ivl_scope_t def = ivl_expr_def(exp);
ivl_signal_t retval = ivl_scope_port(def, 0);
struct vector_info res;
unsigned load_wid;
/* If this is an automatic function, allocate the local storage. */
if (ivl_scope_is_auto(def)) {
fprintf(vvp_out, " %%alloc S_%p;\n", def);
}
/* evaluate the expressions and send the results to the
function ports. */
@ -122,7 +129,7 @@ struct vector_info draw_ufunc_expr(ivl_expr_t exp, unsigned wid)
assert(res.base != 0);
unsigned load_wid = swid;
load_wid = swid;
if (load_wid > ivl_signal_width(retval))
load_wid = ivl_signal_width(retval);
@ -134,6 +141,11 @@ struct vector_info draw_ufunc_expr(ivl_expr_t exp, unsigned wid)
if (load_wid < wid)
pad_expr_in_place(exp, res, swid);
/* If this is an automatic function, free the local storage. */
if (ivl_scope_is_auto(def)) {
fprintf(vvp_out, " %%free S_%p;\n", def);
}
return res;
}
@ -144,6 +156,11 @@ int draw_ufunc_real(ivl_expr_t exp)
int res = 0;
int idx;
/* If this is an automatic function, allocate the local storage. */
if (ivl_scope_is_auto(def)) {
fprintf(vvp_out, " %%alloc S_%p;\n", def);
}
assert(ivl_expr_parms(exp) == (ivl_scope_ports(def)-1));
for (idx = 0 ; idx < ivl_expr_parms(exp) ; idx += 1) {
ivl_signal_t port = ivl_scope_port(def, idx+1);
@ -163,6 +180,10 @@ int draw_ufunc_real(ivl_expr_t exp)
res = allocate_word();
fprintf(vvp_out, " %%load/wr %d, v%p_0;\n", res, retval);
/* If this is an automatic function, free the local storage. */
if (ivl_scope_is_auto(def)) {
fprintf(vvp_out, " %%free S_%p;\n", def);
}
return res;
}

View File

@ -167,6 +167,8 @@ static int get_vpi_taskfunc_signal_arg(struct args_info *result,
case IVL_EX_SELECT: {
ivl_expr_t vexpr = ivl_expr_oper1(expr);
ivl_expr_t bexpr;
assert(vexpr);
/* This code is only for signals or selects. */
@ -177,7 +179,7 @@ static int get_vpi_taskfunc_signal_arg(struct args_info *result,
/* Add &APV<> code here when it is finished. */
if (ivl_expr_oper1(vexpr)) return 0;
ivl_expr_t bexpr = ivl_expr_oper2(expr);
bexpr = ivl_expr_oper2(expr);
assert(bexpr);
/* This is a constant bit/part select. */
@ -339,9 +341,10 @@ static void draw_vpi_taskfunc_args(const char*call_string,
fprintf(vvp_out, "%s", call_string);
for (idx = 0 ; idx < parm_count ; idx += 1) {
struct args_info*ptr;
fprintf(vvp_out, ", %s", args[idx].text);
free(args[idx].text);
struct args_info*ptr;
/* Clear the nested children vectors. */
for (ptr = &args[idx]; ptr != NULL; ptr = ptr->child) {
if (ptr->vec_flag) {

View File

@ -124,11 +124,13 @@ static void eval_logic_into_integer(ivl_expr_t expr, unsigned ix)
{
long imm = get_number_immediate(expr);
if (imm >= 0) {
fprintf(vvp_out, " %%ix/load %u, %ld;\n", ix, imm);
fprintf(vvp_out, " %%ix/load %u, %ld;\n", ix, imm);
} else {
fprintf(vvp_out, " %%ix/load %u, 0; loading %ld\n", ix, imm);
fprintf(vvp_out, " %%ix/sub %u, %ld;\n", ix, -imm);
fprintf(vvp_out, " %%ix/load %u, 0; loading %ld\n", ix, imm);
fprintf(vvp_out, " %%ix/sub %u, %ld;\n", ix, -imm);
}
/* This can not have have a X/Z value so clear bit 4. */
fprintf(vvp_out, " %%mov 4, 0, 1;\n");
}
break;
@ -137,6 +139,7 @@ static void eval_logic_into_integer(ivl_expr_t expr, unsigned ix)
unsigned word = 0;
if (ivl_signal_dimensions(sig) > 0) {
ivl_expr_t ixe;
/* Detect the special case that this is a
variable array. In this case, the ix/getv
@ -144,13 +147,13 @@ static void eval_logic_into_integer(ivl_expr_t expr, unsigned ix)
if (ivl_signal_type(sig) == IVL_SIT_REG) {
struct vector_info rv;
rv = draw_eval_expr(expr, 0);
fprintf(vvp_out, " %%ix/get %u, %u, %u;\n",
fprintf(vvp_out, " %%ix/get %u, %u, %u;\n",
ix, rv.base, rv.wid);
clr_vector(rv);
break;
}
ivl_expr_t ixe = ivl_expr_oper1(expr);
ixe = ivl_expr_oper1(expr);
if (number_is_immediate(ixe, 8*sizeof(unsigned long), 0))
word = get_number_immediate(ixe);
else {
@ -162,7 +165,9 @@ static void eval_logic_into_integer(ivl_expr_t expr, unsigned ix)
break;
}
}
fprintf(vvp_out, " %%ix/getv %u, v%p_%u;\n", ix, sig, word);
char*type = ivl_signal_signed(sig) ? "/s" : "";
fprintf(vvp_out, " %%ix/getv%s %u, v%p_%u;\n", type, ix,
sig, word);
break;
}
@ -934,6 +939,8 @@ static struct vector_info draw_binary_expr_logic(ivl_expr_t exp,
{
ivl_expr_t le = ivl_expr_oper1(exp);
ivl_expr_t re = ivl_expr_oper2(exp);
struct vector_info lv;
struct vector_info rv;
if (ivl_expr_opcode(exp) == '&') {
if (number_is_immediate(re, IMM_WID, 0) && !number_is_unknown(re))
@ -942,9 +949,6 @@ static struct vector_info draw_binary_expr_logic(ivl_expr_t exp,
return draw_logic_immediate(exp, re, le, wid);
}
struct vector_info lv;
struct vector_info rv;
lv = draw_eval_expr_wid(le, wid, STUFF_OK_XZ);
rv = draw_eval_expr_wid(re, wid, STUFF_OK_XZ);
@ -1271,9 +1275,9 @@ static struct vector_info draw_sub_immediate(ivl_expr_t le,
vvp_errors += 1;
}
fprintf(vvp_out, " %%mov %u, %u, %u;\n", tmp, lv.base, wid);
fprintf(vvp_out, " %%mov %u, %u, %u;\n", tmp, lv.base, wid);
lv.base = tmp;
fprintf(vvp_out, " %%subi %u, %lu, %u;\n", lv.base, imm, wid);
fprintf(vvp_out, " %%subi %u, %lu, %u;\n", lv.base, imm, wid);
break;
case 2:
@ -1282,7 +1286,7 @@ static struct vector_info draw_sub_immediate(ivl_expr_t le,
break;
default:
fprintf(vvp_out, " %%subi %u, %lu, %u;\n", lv.base, imm, wid);
fprintf(vvp_out, " %%subi %u, %lu, %u;\n", lv.base, imm, wid);
break;
}
@ -1303,7 +1307,7 @@ static struct vector_info draw_mul_immediate(ivl_expr_t le,
if (imm == 0)
return lv;
fprintf(vvp_out, " %%muli %u, %lu, %u;\n", lv.base, imm, lv.wid);
fprintf(vvp_out, " %%muli %u, %lu, %u;\n", lv.base, imm, lv.wid);
return lv;
}
@ -1621,6 +1625,9 @@ static struct vector_info draw_number_expr(ivl_expr_t exp, unsigned wid)
unsigned nwid;
struct vector_info res;
const char*bits = ivl_expr_bits(exp);
unsigned long val;
unsigned val_bits;
unsigned val_addr;
res.wid = wid;
@ -1675,7 +1682,7 @@ static struct vector_info draw_number_expr(ivl_expr_t exp, unsigned wid)
instruction. */
if ((!number_is_unknown(exp)) && number_is_immediate(exp, IMM_WID,0)) {
unsigned long val = get_number_immediate(exp);
fprintf(vvp_out, " %%movi %u, %lu, %u;\n", res.base, val, wid);
fprintf(vvp_out, " %%movi %u, %lu, %u;\n", res.base, val, wid);
return res;
}
@ -1683,9 +1690,9 @@ static struct vector_info draw_number_expr(ivl_expr_t exp, unsigned wid)
destination. Use the %mov to handle the remaining general
bits. */
idx = 0;
unsigned long val = 0;
unsigned val_bits = 0;
unsigned val_addr = res.base;
val = 0;
val_bits = 0;
val_addr = res.base;
while (idx < nwid) {
char src = 0;
switch (bits[idx]) {
@ -1707,7 +1714,7 @@ static struct vector_info draw_number_expr(ivl_expr_t exp, unsigned wid)
if (val_bits >= IMM_WID
|| (val_bits>0 && src != 0)
|| (val_bits>0 && idx+1==nwid)) {
fprintf(vvp_out, " %%movi %u, %lu, %u;\n",
fprintf(vvp_out, " %%movi %u, %lu, %u;\n",
val_addr, val, val_bits);
val_addr += val_bits;
val_bits = 0;
@ -1715,13 +1722,14 @@ static struct vector_info draw_number_expr(ivl_expr_t exp, unsigned wid)
}
if (src != 0) {
assert(val_bits == 0);
unsigned cnt;
assert(val_bits == 0);
for (cnt = 1 ; idx+cnt < nwid ; cnt += 1)
if (bits[idx+cnt] != bits[idx])
break;
fprintf(vvp_out, " %%mov %u, %c, %u;\n", val_addr, src, cnt);
fprintf(vvp_out, " %%mov %u, %c, %u;\n", val_addr, src, cnt);
val_addr += cnt;
idx += cnt-1;
}
@ -1832,13 +1840,13 @@ static struct vector_info draw_realnum_expr(ivl_expr_t exp, unsigned wid)
continue;
}
fprintf(vvp_out, " %%mov %u, %d, %u;\n", addr, bit, run);
fprintf(vvp_out, " %%mov %u, %d, %u;\n", addr, bit, run);
addr += run;
run = 1;
bit = next_bit;
}
fprintf(vvp_out, " %%mov %u, %d, %u;\n", addr, bit, run);
fprintf(vvp_out, " %%mov %u, %d, %u;\n", addr, bit, run);
return res;
@ -1936,14 +1944,14 @@ static struct vector_info draw_string_expr(ivl_expr_t exp, unsigned wid)
}
}
}
fprintf(vvp_out, " %%movi %u, %u, %u;\n", res.base+idx,bits,trans);
fprintf(vvp_out, " %%movi %u, %u, %u;\n", res.base+idx,bits,trans);
idx += trans;
}
/* Pad the number up to the expression width. */
if (idx < wid)
fprintf(vvp_out, " %%mov %u, 0, %u;\n", res.base+idx, wid-idx);
fprintf(vvp_out, " %%mov %u, 0, %u;\n", res.base+idx, wid-idx);
if (res.base >= 8)
save_expression_lookaside(res.base, exp, wid);
@ -1976,9 +1984,9 @@ void pad_expr_in_place(ivl_expr_t exp, struct vector_info res, unsigned swid)
/* The %movi is faster for larger widths, but for very
small counts, the %mov is faster. */
if (count > 4)
fprintf(vvp_out, " %%movi %u, 0, %u;\n", base, count);
fprintf(vvp_out, " %%movi %u, 0, %u;\n", base, count);
else
fprintf(vvp_out, " %%mov %u, 0, %u;\n", base, count);
fprintf(vvp_out, " %%mov %u, 0, %u;\n", base, count);
}
}
@ -2011,15 +2019,15 @@ static void draw_signal_dest(ivl_expr_t exp, struct vector_info res,
draw_eval_expr_into_integer(ix, 3);
if (add_index < 0) {
fprintf(vvp_out, " %%load/av %u, v%p, %u;\n",
fprintf(vvp_out, " %%load/av %u, v%p, %u;\n",
res.base, sig, swid);
pad_expr_in_place(exp, res, swid);
} else {
const char*sign_flag = (add_index>0)? "/s" : "";
/* Add an immediate value to an array value. */
fprintf(vvp_out, " %%ix/load 0, %lu;\n", immediate);
fprintf(vvp_out, " %%load/avp0%s %u, v%p, %u;\n",
fprintf(vvp_out, " %%ix/load 0, %lu;\n", immediate);
fprintf(vvp_out, " %%load/avp0%s %u, v%p, %u;\n",
sign_flag, res.base, sig, res.wid);
}
return;
@ -2027,11 +2035,12 @@ static void draw_signal_dest(ivl_expr_t exp, struct vector_info res,
if (ivl_signal_data_type(sig) == IVL_VT_REAL) {
int tmp;
assert(add_index < 0);
int tmp = allocate_word();
fprintf(vvp_out, " %%load/wr %d, v%p_%u;\n", tmp, sig, word);
fprintf(vvp_out, " %%cvt/vr %u, %d, %u;\n", res.base, tmp, res.wid);
tmp = allocate_word();
fprintf(vvp_out, " %%load/wr %d, v%p_%u;\n", tmp, sig, word);
fprintf(vvp_out, " %%cvt/vr %u, %d, %u;\n", res.base, tmp, res.wid);
clr_word(tmp);
} else if (add_index >= 0) {
@ -2042,8 +2051,8 @@ static void draw_signal_dest(ivl_expr_t exp, struct vector_info res,
if (immediate >= 0) {
fprintf(vvp_out, " %%ix/load 0, %lu;\n", immediate);
} else {
fprintf(vvp_out, " %%ix/load 0, 0; immediate=%ld\n", immediate);
fprintf(vvp_out, " %%ix/sub 0, %ld;\n", -immediate);
fprintf(vvp_out, " %%ix/load 0, 0; immediate=%ld\n", immediate);
fprintf(vvp_out, " %%ix/sub 0, %ld;\n", -immediate);
}
fprintf(vvp_out, " %%load/vp0%s %u, v%p_%u, %u;\n", sign_flag,
res.base, sig,word, res.wid);
@ -2107,7 +2116,7 @@ static struct vector_info draw_select_array(ivl_expr_t sube,
shiv = draw_eval_expr(bit_idx, STUFF_OK_XZ|STUFF_OK_RO);
draw_eval_expr_into_integer(ix, 3);
fprintf(vvp_out, " %%ix/get 0, %u, %u;\n", shiv.base, shiv.wid);
fprintf(vvp_out, " %%ix/get 0, %u, %u;\n", shiv.base, shiv.wid);
if (shiv.base >= 8)
clr_vector(shiv);
@ -2122,7 +2131,7 @@ static struct vector_info draw_select_array(ivl_expr_t sube,
}
for (idx = 0 ; idx < wid ; idx += 1) {
fprintf(vvp_out, " %%load/avx.p %u, v%p, 0;\n", res.base+idx, sig);
fprintf(vvp_out, " %%load/avx.p %u, v%p, 0;\n", res.base+idx, sig);
}
return res;
@ -2138,6 +2147,7 @@ static struct vector_info draw_select_signal(ivl_expr_t sube,
/* Use this word of the signal. */
unsigned use_word = 0;
unsigned use_wid;
/* 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
@ -2167,7 +2177,7 @@ static struct vector_info draw_select_signal(ivl_expr_t sube,
res.base = allocate_vector(wid);
res.wid = wid;
assert(res.base);
fprintf(vvp_out, " %%load/v %u, v%p_%u, %u; Only need %u of %u bits\n",
fprintf(vvp_out, " %%load/v %u, v%p_%u, %u; Only need %u of %u bits\n",
res.base, sig, use_word, bit_wid, bit_wid, ivl_expr_width(sube));
save_signal_lookaside(res.base, sig, use_word, bit_wid);
@ -2186,14 +2196,14 @@ static struct vector_info draw_select_signal(ivl_expr_t sube,
res.wid = wid;
assert(res.base);
unsigned use_wid = res.wid;
use_wid = res.wid;
if (use_wid > bit_wid)
use_wid = bit_wid;
fprintf(vvp_out, " %%load/x1p %u, v%p_%u, %u;\n",
fprintf(vvp_out, " %%load/x1p %u, v%p_%u, %u;\n",
res.base, sig, use_word, use_wid);
if (use_wid < res.wid)
fprintf(vvp_out, " %%movi %u, 0, %u;\n",
fprintf(vvp_out, " %%movi %u, 0, %u;\n",
res.base + use_wid, res.wid - use_wid);
return res;
@ -2581,15 +2591,15 @@ static struct vector_info draw_unary_expr(ivl_expr_t exp, unsigned wid)
result a 1. */
if (res.base == 1) {
res.base = allocate_vector(wid);
fprintf(vvp_out, " %%movi %d, 1, %u;\n",
fprintf(vvp_out, " %%movi %d, 1, %u;\n",
res.base, res.wid);
break;
}
fprintf(vvp_out, " %%cmpi/s %d, 0, %u;\n", res.base, res.wid);
fprintf(vvp_out, " %%jmp/0xz T_%u.%u, 5;\n", thread_count, local_count);
fprintf(vvp_out, " %%inv %d, %u;\n", res.base, res.wid);
fprintf(vvp_out, " %%addi %d, 1, %u;\n", res.base, res.wid);
fprintf(vvp_out, " %%cmpi/s %d, 0, %u;\n", res.base, res.wid);
fprintf(vvp_out, " %%jmp/0xz T_%u.%u, 5;\n", thread_count, local_count);
fprintf(vvp_out, " %%inv %d, %u;\n", res.base, res.wid);
fprintf(vvp_out, " %%addi %d, 1, %u;\n", res.base, res.wid);
fprintf(vvp_out, "T_%u.%u ;\n", thread_count, local_count);
local_count += 1;
break;

View File

@ -72,9 +72,12 @@ static int draw_binary_real(ivl_expr_t exp)
case 'X':
{
struct vector_info vi;
int res;
const char*sign_flag;
vi = draw_eval_expr(exp, STUFF_OK_XZ);
int res = allocate_word();
const char*sign_flag = ivl_expr_signed(exp)? "/s" : "";
res = allocate_word();
sign_flag = ivl_expr_signed(exp)? "/s" : "";
fprintf(vvp_out, " %%ix/get%s %d, %u, %u;\n",
sign_flag, res, vi.base, vi.wid);
@ -113,7 +116,7 @@ static int draw_binary_real(ivl_expr_t exp)
fprintf(vvp_out, " %%pow/wr %d, %d;\n", l, r);
break;
case 'm': { // min(l,r)
case 'm': { /* min(l,r) */
int lab_out = local_count++;
int lab_r = local_count++;
/* If r is NaN, the go out and accept l as result. */
@ -131,7 +134,7 @@ static int draw_binary_real(ivl_expr_t exp)
break;
}
case 'M': { // max(l,r)
case 'M': { /* max(l,r) */
int lab_out = local_count++;
int lab_r = local_count++;
/* If r is NaN, the go out and accept l as result. */
@ -168,28 +171,49 @@ static int draw_number_real(ivl_expr_t exp)
unsigned long mant = 0, mask = -1UL;
int vexp = 0x1000;
for (idx = 0 ; idx < wid ; idx += 1) {
mask <<= 1;
if (bits[idx] == '1')
mant |= 1 << idx;
}
/* If this is a negative number, then arrange for the 2's
complement to be calculated as we scan through the
value. Real values are sign-magnitude, and this negation
gets us a magnitide. */
/* If this is actually a negative number, then get the
positive equivalent, and set the sign bit in the exponent
field.
To get the positive equivalent of mant we need to take the
negative of the mantissa (0-mant) but also be aware that
the bits may not have been as many bits as the width of the
mant variable. This would lead to spurious '1' bits in the
high bits of mant that are masked by ~((-1UL)<<wid). */
int negate = 0;
int carry = 0;
if (ivl_expr_signed(exp) && (bits[wid-1] == '1')) {
mant = (0-mant) & ~(mask);
vexp |= 0x4000;
negate = 1;
carry = 1;
}
fprintf(vvp_out, " %%loadi/wr %d, %lu, %d; load(num)= %c%lu\n",
res, mant, vexp, (vexp&0x4000)? '-' : '+', mant);
for (idx = 0 ; idx < wid && idx < 8*sizeof(mant) ; idx += 1) {
mask <<= 1;
int cur_bit = bits[idx] == '1'? 1 : 0;
if (negate) {
cur_bit ^= 1;
cur_bit += carry;
carry = (cur_bit >> 1) & 1;
cur_bit &= 1;
}
if (cur_bit) mant |= 1 << idx;
}
for ( ; idx < wid ; idx += 1) {
if (ivl_expr_signed(exp) && (bits[idx] == bits[8*sizeof(mant)-1]))
continue;
if (bits[idx] == '0')
continue;
fprintf(stderr, "internal error: mantissa doesn't fit!\n");
assert(0);
}
/* If required, add in a sign bit. */
if (negate)
vexp |= 0x4000;
fprintf(vvp_out, " %%loadi/wr %d, %lu, %d; load(num)= %c%lu (wid=%u)\n",
res, mant, vexp, (vexp&0x4000)? '-' : '+', mant, wid);
return res;
}
@ -430,14 +454,20 @@ static int draw_ternary_real(ivl_expr_t exp)
static int draw_unary_real(ivl_expr_t exp)
{
ivl_expr_t sube;
int sub;
/* If the opcode is a ~ then the sub expression must not be a
* real expression, so use vector evaluation and then convert
* that result to a real value. */
if (ivl_expr_opcode(exp) == '~') {
struct vector_info vi;
int res;
const char*sign_flag;
vi = draw_eval_expr(exp, STUFF_OK_XZ);
int res = allocate_word();
const char*sign_flag = ivl_expr_signed(exp)? "/s" : "";
res = allocate_word();
sign_flag = ivl_expr_signed(exp)? "/s" : "";
fprintf(vvp_out, " %%ix/get%s %d, %u, %u;\n",
sign_flag, res, vi.base, vi.wid);
@ -449,9 +479,12 @@ static int draw_unary_real(ivl_expr_t exp)
if (ivl_expr_opcode(exp) == '!') {
struct vector_info vi;
int res;
const char*sign_flag;
vi = draw_eval_expr(exp, STUFF_OK_XZ);
int res = allocate_word();
const char*sign_flag = ivl_expr_signed(exp)? "/s" : "";
res = allocate_word();
sign_flag = ivl_expr_signed(exp)? "/s" : "";
fprintf(vvp_out, " %%ix/get%s %d, %u, %u;\n",
sign_flag, res, vi.base, vi.wid);
@ -461,9 +494,8 @@ static int draw_unary_real(ivl_expr_t exp)
return res;
}
ivl_expr_t sube = ivl_expr_oper1(exp);
int sub = draw_eval_real(sube);
sube = ivl_expr_oper1(exp);
sub = draw_eval_real(sube);
if (ivl_expr_opcode(exp) == '+')
return sub;

View File

@ -84,6 +84,8 @@ static void draw_modpath_record(const char*label, const char*driver,
int ppos = ivl_path_source_posedge(path);
int pneg = ivl_path_source_negedge(path);
const char*edge = ppos? " +" : pneg ? " -" : "";
ivl_signal_t src_sig;
fprintf(vvp_out, ",\n %s%s", src_drivers[idx], edge);
fprintf(vvp_out,
" (%"PRIu64",%"PRIu64",%"PRIu64
@ -109,7 +111,7 @@ static void draw_modpath_record(const char*label, const char*driver,
fprintf(vvp_out, ")");
ivl_signal_t src_sig = find_path_source_port(path);
src_sig = find_path_source_port(path);
fprintf(vvp_out, " v%p_0", src_sig);
}
@ -140,9 +142,10 @@ void cleanup_modpath(void)
{
while (modpath_list) {
struct modpath_item*cur = modpath_list;
char modpath_label[64];
modpath_list = cur->next;
char modpath_label[64];
snprintf(modpath_label, sizeof modpath_label, "V_%p/m", cur->path_sig);
draw_modpath_record(modpath_label, cur->drive_label, cur->path_sig);
free(cur->drive_label);

View File

@ -41,23 +41,23 @@ static struct allocation_score_s {
/* This is the largest bit to have lookaside values. */
static unsigned lookaside_top = 0;
static inline ivl_expr_t peek_exp(unsigned addr)
static __inline__ ivl_expr_t peek_exp(unsigned addr)
{
return allocation_map[addr].exp;
}
static inline unsigned peek_exp_bit(unsigned addr)
static __inline__ unsigned peek_exp_bit(unsigned addr)
{
return allocation_map[addr].exp_bit;
}
static inline void set_exp(unsigned addr, ivl_expr_t exp, unsigned ebit)
static __inline__ void set_exp(unsigned addr, ivl_expr_t exp, unsigned ebit)
{
allocation_map[addr].exp = exp;
allocation_map[addr].exp_bit = ebit;
}
static inline void set_sig(unsigned addr, ivl_signal_t exp, unsigned sig_word, unsigned ebit)
static __inline__ void set_sig(unsigned addr, ivl_signal_t exp, unsigned sig_word, unsigned ebit)
{
allocation_map[addr].sig = exp;
allocation_map[addr].sig_word = sig_word;

View File

@ -3,5 +3,4 @@ functor:synth
functor:syn-rules
functor:cprop
functor:nodangle
-t:dll
flag:DLL=vvp.tgt

View File

@ -26,10 +26,27 @@
# include <sys/types.h>
# include <sys/stat.h>
static const char*version_string =
"Icarus Verilog VVP Code Generator " VERSION "\n"
" This program is free software; you can redistribute it and/or modify\n"
" it under the terms of the GNU General Public License as published by\n"
" the Free Software Foundation; either version 2 of the License, or\n"
" (at your option) any later version.\n"
"\n"
" This program is distributed in the hope that it will be useful,\n"
" but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
" GNU General Public License for more details.\n"
"\n"
" You should have received a copy of the GNU General Public License\n"
" along with this program; if not, write to the Free Software\n"
" Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA\n"
;
FILE*vvp_out = 0;
int vvp_errors = 0;
inline static void draw_execute_header(ivl_design_t des)
__inline__ static void draw_execute_header(ivl_design_t des)
{
#if !defined(__MINGW32__)
const char*cp = ivl_design_flag(des, "VVP_EXECUTABLE");
@ -40,7 +57,7 @@ inline static void draw_execute_header(ivl_design_t des)
#endif
}
inline static void draw_module_declarations(ivl_design_t des)
__inline__ static void draw_module_declarations(ivl_design_t des)
{
const char*cp = ivl_design_flag(des, "VPI_MODULE_LIST");
@ -67,6 +84,8 @@ int target_design(ivl_design_t des)
int rc;
ivl_scope_t *roots;
unsigned nroots, i;
unsigned size;
unsigned idx;
const char*path = ivl_design_flag(des, "-o");
assert(path);
@ -106,10 +125,9 @@ int target_design(ivl_design_t des)
rc = ivl_design_process(des, draw_process, 0);
/* Dump the file name table. */
unsigned size = ivl_file_table_size();
size = ivl_file_table_size();
fprintf(vvp_out, "# The file index is used to find the file name in "
"the following table.\n:file_names %u;\n", size);
unsigned idx;
for (idx = 0; idx < size; idx++) {
fprintf(vvp_out, " \"%s\";\n", ivl_file_table_item(idx));
}
@ -119,3 +137,11 @@ int target_design(ivl_design_t des)
return rc + vvp_errors;
}
const char* target_query(const char*key)
{
if (strcmp(key,"version") == 0)
return version_string;
return 0;
}

View File

@ -1,4 +1,3 @@
functor:cprop
functor:nodangle
-t:dll
flag:DLL=vvp.tgt

View File

@ -46,4 +46,4 @@
* Isolate configure from containing config.h
*
*/
#endif // __vvp_config_H
#endif /* __vvp_config_H */

View File

@ -25,6 +25,10 @@
#endif
# include <stdlib.h>
#ifdef __MINGW32__ /* MinGW has inconsistent %p output. */
#define snprintf _snprintf
#endif
static int show_statement(ivl_statement_t net, ivl_scope_t sscope);
unsigned local_count = 0;
@ -220,7 +224,8 @@ static void set_to_lvariable(ivl_lval_t lval,
static void assign_to_array_word(ivl_signal_t lsig, ivl_expr_t word_ix,
unsigned bit, unsigned delay, ivl_expr_t dexp,
ivl_expr_t part_off_ex, unsigned width)
ivl_expr_t part_off_ex, unsigned width,
unsigned nevents)
{
unsigned skip_assign = transient_id++;
@ -232,64 +237,52 @@ static void assign_to_array_word(ivl_signal_t lsig, ivl_expr_t word_ix,
part_off_ex = 0;
}
if (dexp == 0) {
/* Constant delay... */
if (number_is_immediate(word_ix, 64, 0)) {
fprintf(vvp_out, " %%ix/load 3, %lu; address\n",
get_number_immediate(word_ix));
} else {
/* Calculate array word index into index register 3 */
draw_eval_expr_into_integer(word_ix, 3);
/* Skip assignment if word expression is not defined. */
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_assign);
}
/* Store expression width into index word 0 */
fprintf(vvp_out, " %%ix/load 0, %u; word width\n", width);
if (part_off_ex) {
draw_eval_expr_into_integer(part_off_ex, 1);
/* If the index expression has XZ bits, skip the assign. */
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_assign);
} else {
/* Store word part select base into index 1 */
fprintf(vvp_out, " %%ix/load 1, %u; part base\n", part_off);
}
fprintf(vvp_out, " %%assign/av v%p, %u, %u;\n", lsig,
delay, bit);
/* This code is common to all the different types of array delays. */
if (number_is_immediate(word_ix, 64, 0)) {
fprintf(vvp_out, " %%ix/load 3, %lu; address\n",
get_number_immediate(word_ix));
} else {
/* Calculate array word index into index register 3 */
draw_eval_expr_into_integer(word_ix, 3);
/* Skip assignment if word expression is not defined. */
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_assign);
}
/* Store expression width into index word 0 */
fprintf(vvp_out, " %%ix/load 0, %u; word width\n", width);
if (part_off_ex) {
draw_eval_expr_into_integer(part_off_ex, 1);
/* If the index expression has XZ bits, skip the assign. */
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_assign);
} else {
/* Store word part select into index 1 */
fprintf(vvp_out, " %%ix/load 1, %u; part off\n", part_off);
}
if (dexp != 0) {
/* Calculated delay... */
int delay_index = allocate_word();
draw_eval_expr_into_integer(dexp, delay_index);
if (number_is_immediate(word_ix, 64, 0)) {
fprintf(vvp_out, " %%ix/load 3, %lu; address\n",
get_number_immediate(word_ix));
} else {
/* Calculate array word index into index register 3 */
draw_eval_expr_into_integer(word_ix, 3);
/* Skip assignment if word expression is not defined. */
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_assign);
}
/* Store expression width into index word 0 */
fprintf(vvp_out, " %%ix/load 0, %u; word width\n", width);
if (part_off_ex) {
draw_eval_expr_into_integer(part_off_ex, 1);
/* If the index expression has XZ bits, skip the assign. */
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_assign);
} else {
/* Store word part select into index 1 */
fprintf(vvp_out, " %%ix/load 1, %u; part off\n", part_off);
}
fprintf(vvp_out, " %%assign/av/d v%p, %d, %u;\n", lsig,
delay_index, bit);
delay_index, bit);
clr_word(delay_index);
} else if (nevents != 0) {
/* Event control delay... */
fprintf(vvp_out, " %%assign/av/e v%p, %u;\n", lsig, bit);
} else {
/* Constant delay... */
fprintf(vvp_out, " %%assign/av v%p, %u, %u;\n", lsig,
delay, bit);
}
fprintf(vvp_out, "t_%u ;\n", skip_assign);
if (nevents != 0) fprintf(vvp_out, " %%evctl/c;\n");
clear_expression_lookaside();
}
static void assign_to_lvector(ivl_lval_t lval, unsigned bit,
unsigned delay, ivl_expr_t dexp,
unsigned width)
unsigned width, unsigned nevents)
{
ivl_signal_t sig = ivl_lval_sig(lval);
ivl_expr_t part_off_ex = ivl_lval_part_off(lval);
@ -300,7 +293,8 @@ static void assign_to_lvector(ivl_lval_t lval, unsigned bit,
if (ivl_signal_dimensions(sig) > 0) {
assert(word_ix);
assign_to_array_word(sig, word_ix, bit, delay, dexp, part_off_ex, width);
assign_to_array_word(sig, word_ix, bit, delay, dexp, part_off_ex,
width, nevents);
return;
}
@ -316,16 +310,7 @@ static void assign_to_lvector(ivl_lval_t lval, unsigned bit,
if (part_off_ex) {
unsigned skip_assign = transient_id++;
if (dexp == 0) {
/* Constant delay... */
draw_eval_expr_into_integer(part_off_ex, 1);
/* If the index expression has XZ bits, skip the assign. */
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_assign);
fprintf(vvp_out, " %%ix/load 0, %u;\n", width);
fprintf(vvp_out, " %%assign/v0/x1 v%p_%lu, %u, %u;\n",
sig, use_word, delay, bit);
fprintf(vvp_out, "t_%u ;\n", skip_assign);
} else {
if (dexp != 0) {
/* Calculated delay... */
int delay_index = allocate_word();
draw_eval_expr_into_integer(dexp, delay_index);
@ -337,6 +322,25 @@ static void assign_to_lvector(ivl_lval_t lval, unsigned bit,
sig, use_word, delay_index, bit);
fprintf(vvp_out, "t_%u ;\n", skip_assign);
clr_word(delay_index);
} else if (nevents != 0) {
/* Event control delay... */
draw_eval_expr_into_integer(part_off_ex, 1);
/* If the index expression has XZ bits, skip the assign. */
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_assign);
fprintf(vvp_out, " %%ix/load 0, %u;\n", width);
fprintf(vvp_out, " %%assign/v0/x1/e v%p_%lu, %u;\n",
sig, use_word, bit);
fprintf(vvp_out, "t_%u ;\n", skip_assign);
fprintf(vvp_out, " %%evctl/c;\n");
} else {
/* Constant delay... */
draw_eval_expr_into_integer(part_off_ex, 1);
/* If the index expression has XZ bits, skip the assign. */
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_assign);
fprintf(vvp_out, " %%ix/load 0, %u;\n", width);
fprintf(vvp_out, " %%assign/v0/x1 v%p_%lu, %u, %u;\n",
sig, use_word, delay, bit);
fprintf(vvp_out, "t_%u ;\n", skip_assign);
}
} else if (part_off>0 || ivl_lval_width(lval)!=ivl_signal_width(sig)) {
@ -345,14 +349,7 @@ static void assign_to_lvector(ivl_lval_t lval, unsigned bit,
single-bit set instruction. */
assert(ivl_lval_width(lval) == width);
if (dexp == 0) {
/* Constant delay... */
fprintf(vvp_out, " %%ix/load 0, %u;\n", width);
fprintf(vvp_out, " %%ix/load 1, %u;\n", part_off);
fprintf(vvp_out, " %%assign/v0/x1 v%p_%lu, %u, %u;\n",
sig, use_word, delay, bit);
} else {
if (dexp != 0) {
/* Calculated delay... */
int delay_index = allocate_word();
draw_eval_expr_into_integer(dexp, delay_index);
@ -361,14 +358,33 @@ static void assign_to_lvector(ivl_lval_t lval, unsigned bit,
fprintf(vvp_out, " %%assign/v0/x1/d v%p_%lu, %d, %u;\n",
sig, use_word, delay_index, bit);
clr_word(delay_index);
} else if (nevents != 0) {
/* Event control delay... */
fprintf(vvp_out, " %%ix/load 0, %u;\n", width);
fprintf(vvp_out, " %%ix/load 1, %u;\n", part_off);
fprintf(vvp_out, " %%assign/v0/x1/e v%p_%lu, %u;\n",
sig, use_word, bit);
} else {
/* Constant delay... */
fprintf(vvp_out, " %%ix/load 0, %u;\n", width);
fprintf(vvp_out, " %%ix/load 1, %u;\n", part_off);
fprintf(vvp_out, " %%assign/v0/x1 v%p_%lu, %u, %u;\n",
sig, use_word, delay, bit);
}
} else if (dexp != 0) {
/* Calculated delay... */
draw_eval_expr_into_integer(dexp, 1);
fprintf(vvp_out, " %%ix/load 0, %u;\n", width);
fprintf(vvp_out, " %%assign/v0/d v%p_%lu, 1, %u;\n",
sig, use_word, bit);
} else if (nevents != 0) {
/* Event control delay... */
fprintf(vvp_out, " %%ix/load 0, %u;\n", width);
fprintf(vvp_out, " %%assign/v0/e v%p_%lu, %u;\n",
sig, use_word, bit);
} else {
/* Constant delay... */
fprintf(vvp_out, " %%ix/load 0, %u;\n", width);
fprintf(vvp_out, " %%assign/v0 v%p_%lu, %u, %u;\n",
sig, use_word, delay, bit);
@ -412,6 +428,14 @@ static void set_vec_to_lval(ivl_statement_t net, struct vector_info res)
}
}
static int show_stmt_alloc(ivl_statement_t net)
{
ivl_scope_t scope = ivl_stmt_call(net);
fprintf(vvp_out, " %%alloc S_%p;\n", scope);
return 0;
}
static int show_stmt_assign_vector(ivl_statement_t net)
{
ivl_expr_t rval = ivl_stmt_rval(net);
@ -531,7 +555,8 @@ static int show_stmt_assign_nb_real(ivl_statement_t net)
unsigned long use_word = 0;
/* thread address for a word value. */
int word;
unsigned long delay;
unsigned long delay = 0;
unsigned nevents = ivl_stmt_nevent(net);
/* Must be exactly 1 l-value. */
assert(ivl_stmt_lvals(net) == 1);
@ -547,20 +572,29 @@ static int show_stmt_assign_nb_real(ivl_statement_t net)
use_word = get_number_immediate(word_ix);
}
delay = 0;
if (del && (ivl_expr_type(del) == IVL_EX_ULONG)) {
delay = ivl_expr_uvalue(del);
del = 0;
}
/* XXXX For now, presume delays are constant. */
assert(del == 0);
/* Evaluate the r-value */
word = draw_eval_real(rval);
fprintf(vvp_out, " %%assign/wr v%p_%lu, %lu, %u;\n",
sig, use_word, delay, word);
/* We need to calculate the delay expression. */
if (del) {
assert(nevents == 0);
int delay_index = allocate_word();
draw_eval_expr_into_integer(del, delay_index);
fprintf(vvp_out, " %%assign/wr/d v%p_%lu, %d, %u;\n",
sig, use_word, delay_index, word);
clr_word(delay_index);
} else if (nevents) {
fprintf(vvp_out, " %%assign/wr/e v%p_%lu, %u;\n",
sig, use_word, word);
} else {
fprintf(vvp_out, " %%assign/wr v%p_%lu, %lu, %u;\n",
sig, use_word, delay, word);
}
clr_word(word);
@ -573,6 +607,51 @@ static int show_stmt_assign_nb(ivl_statement_t net)
ivl_expr_t rval = ivl_stmt_rval(net);
ivl_expr_t del = ivl_stmt_delay_expr(net);
ivl_signal_t sig;
unsigned nevents = ivl_stmt_nevent(net);
/* If we have an event control build the control structure. */
if (nevents) {
assert(del == 0);
ivl_expr_t cnt = ivl_stmt_cond_expr(net);
unsigned long count = 1;
if (cnt && (ivl_expr_type(cnt) == IVL_EX_ULONG)) {
count = ivl_expr_uvalue(cnt);
cnt = 0;
}
char name[256];
if (nevents == 1) {
ivl_event_t ev = ivl_stmt_events(net, 0);
snprintf(name, sizeof(name), "E_%p", ev);
} else {
unsigned idx;
static unsigned int cascade_counter = 0;
ivl_event_t ev = ivl_stmt_events(net, 0);
fprintf(vvp_out, "Eassign_%u .event/or E_%p",
cascade_counter, ev);
for (idx = 1; idx < nevents; idx += 1) {
ev = ivl_stmt_events(net, idx);
fprintf(vvp_out, ", E_%p", ev);
}
snprintf(name, sizeof(name), "Eassign_%u", cascade_counter);
cascade_counter += 1;
}
if (cnt) {
int count_index = allocate_word();
char*type = ivl_expr_signed(cnt) ? "/s" : "";
draw_eval_expr_into_integer(cnt, count_index);
fprintf(vvp_out, " %%evctl%s %s, %d;\n", type, name,
count_index);
clr_word(count_index);
} else {
fprintf(vvp_out, " %%evctl/i %s, %lu;\n", name, count);
}
} else {
assert(ivl_stmt_cond_expr(net) == 0);
}
unsigned long delay = 0;
@ -600,15 +679,15 @@ static int show_stmt_assign_nb(ivl_statement_t net)
for (lidx = 0 ; lidx < ivl_stmt_lvals(net) ; lidx += 1) {
unsigned bit_limit = wid - cur_rbit;
unsigned bidx;
lval = ivl_stmt_lval(net, lidx);
if (bit_limit > ivl_lval_width(lval))
bit_limit = ivl_lval_width(lval);
unsigned bidx;
bidx = res.base < 4? res.base : (res.base+cur_rbit);
assign_to_lvector(lval, bidx, delay, del, bit_limit);
assign_to_lvector(lval, bidx, delay, del, bit_limit, nevents);
cur_rbit += bit_limit;
@ -861,6 +940,8 @@ static int show_stmt_case_r(ivl_statement_t net, ivl_scope_t sscope)
static void force_real_to_lval(ivl_statement_t net, int res)
{
const char*command_name;
ivl_lval_t lval;
ivl_signal_t lsig;
switch (ivl_statement_type(net)) {
case IVL_ST_CASSIGN:
@ -876,8 +957,8 @@ static void force_real_to_lval(ivl_statement_t net, int res)
}
assert(ivl_stmt_lvals(net) == 1);
ivl_lval_t lval = ivl_stmt_lval(net, 0);
ivl_signal_t lsig = ivl_lval_sig(lval);
lval = ivl_stmt_lval(net, 0);
lsig = ivl_lval_sig(lval);
assert(ivl_lval_width(lval) == 1);
assert(ivl_lval_part_off(lval) == 0);
@ -962,10 +1043,11 @@ static void force_vector_to_lval(ivl_statement_t net, struct vector_info rvec)
static void force_link_rval(ivl_statement_t net, ivl_expr_t rval)
{
ivl_signal_t rsig;;
ivl_signal_t rsig;
ivl_lval_t lval;
ivl_signal_t lsig;
const char*command_name;
ivl_expr_t part_off_ex;
ivl_expr_t lword_idx, rword_idx;
unsigned long use_lword = 0, use_rword = 0;
@ -993,7 +1075,7 @@ static void force_link_rval(ivl_statement_t net, ivl_expr_t rval)
/* We do not currently support driving a signal to a bit or
* part select (this could give us multiple drivers). */
ivl_expr_t 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) ||
(part_off_ex && get_number_immediate(part_off_ex) != 0)) {
fprintf(stderr, "%s:%u: vvp-tgt sorry: cannot %s signal to "
@ -1060,9 +1142,13 @@ static int show_stmt_cassign(ivl_statement_t net)
static int show_stmt_deassign(ivl_statement_t net)
{
ivl_signal_t sig = ivl_lval_sig(ivl_stmt_lval(net, 0));
unsigned lidx;
if (sig && ivl_signal_data_type(sig) == IVL_VT_REAL) {
ivl_lval_t lval;
assert(ivl_stmt_lvals(net) == 1);
ivl_lval_t lval = ivl_stmt_lval(net, 0);
lval = ivl_stmt_lval(net, 0);
assert(ivl_lval_width(lval) == 1);
assert(ivl_lval_part_off(lval) == 0);
assert(ivl_lval_idx(lval) == 0);
@ -1071,21 +1157,22 @@ static int show_stmt_deassign(ivl_statement_t net)
return 0;
}
unsigned lidx;
for (lidx = 0 ; lidx < ivl_stmt_lvals(net) ; lidx += 1) {
ivl_lval_t lval = ivl_stmt_lval(net, lidx);
ivl_signal_t lsig = ivl_lval_sig(lval);
ivl_expr_t word_idx = ivl_lval_idx(lval);
unsigned long use_word = 0;
unsigned use_wid;
ivl_expr_t part_off_ex;
unsigned part_off;
assert(lsig != 0);
assert(ivl_lval_mux(lval) == 0);
unsigned use_wid = ivl_lval_width(lval);
ivl_expr_t part_off_ex = ivl_lval_part_off(lval);
unsigned part_off = 0;
use_wid = ivl_lval_width(lval);
part_off_ex = ivl_lval_part_off(lval);
part_off = 0;
if (part_off_ex != 0) {
assert(number_is_immediate(part_off_ex, 64, 0));
part_off = get_number_immediate(part_off_ex);
@ -1327,6 +1414,14 @@ static int show_stmt_fork(ivl_statement_t net, ivl_scope_t sscope)
return rc;
}
static int show_stmt_free(ivl_statement_t net)
{
ivl_scope_t scope = ivl_stmt_call(net);
fprintf(vvp_out, " %%free S_%p;\n", scope);
return 0;
}
/*
* noop statements are implemented by doing nothing.
*/
@ -1338,11 +1433,14 @@ static int show_stmt_noop(ivl_statement_t net)
static int show_stmt_release(ivl_statement_t net)
{
ivl_signal_t sig = ivl_lval_sig(ivl_stmt_lval(net, 0));
unsigned lidx;
if (sig && ivl_signal_data_type(sig) == IVL_VT_REAL) {
unsigned type = 0;
ivl_lval_t lval;
assert(ivl_stmt_lvals(net) == 1);
ivl_lval_t lval = ivl_stmt_lval(net, 0);
lval = ivl_stmt_lval(net, 0);
assert(ivl_lval_width(lval) == 1);
assert(ivl_lval_part_off(lval) == 0);
assert(ivl_lval_idx(lval) == 0);
@ -1353,8 +1451,6 @@ static int show_stmt_release(ivl_statement_t net)
return 0;
}
unsigned lidx;
for (lidx = 0 ; lidx < ivl_stmt_lvals(net) ; lidx += 1) {
ivl_lval_t lval = ivl_stmt_lval(net, lidx);
ivl_signal_t lsig = ivl_lval_sig(lval);
@ -1362,12 +1458,16 @@ static int show_stmt_release(ivl_statement_t net)
ivl_expr_t word_idx = ivl_lval_idx(lval);
unsigned long use_word = 0;
unsigned use_wid;
ivl_expr_t part_off_ex;
unsigned part_off;
assert(lsig != 0);
assert(ivl_lval_mux(lval) == 0);
unsigned use_wid = ivl_lval_width(lval);
ivl_expr_t part_off_ex = ivl_lval_part_off(lval);
unsigned part_off = 0;
use_wid = ivl_lval_width(lval);
part_off_ex = ivl_lval_part_off(lval);
part_off = 0;
if (part_off_ex != 0) {
assert(number_is_immediate(part_off_ex, 64, 0));
part_off = get_number_immediate(part_off_ex);
@ -1574,6 +1674,10 @@ static int show_statement(ivl_statement_t net, ivl_scope_t sscope)
switch (code) {
case IVL_ST_ALLOC:
rc += show_stmt_alloc(net);
break;
case IVL_ST_ASSIGN:
rc += show_stmt_assign(net);
break;
@ -1635,6 +1739,10 @@ static int show_statement(ivl_statement_t net, ivl_scope_t sscope)
rc += show_stmt_fork(net, sscope);
break;
case IVL_ST_FREE:
rc += show_stmt_free(net);
break;
case IVL_ST_NOOP:
rc += show_stmt_noop(net);
break;

View File

@ -36,7 +36,7 @@
* Escape non-symbol characters in ids, and quotes in strings.
*/
inline static char hex_digit(unsigned i)
__inline__ static char hex_digit(unsigned i)
{
i &= 0xf;
return i>=10 ? i-10+'A' : i+'0';
@ -322,6 +322,8 @@ char* draw_Cr_to_string(double value)
char tmp[256];
uint64_t mant = 0;
int sign, expo, vexp;
double fract;
if (isinf(value)) {
if (value > 0)
@ -335,19 +337,18 @@ char* draw_Cr_to_string(double value)
return strdup(tmp);
}
int sign = 0;
sign = 0;
if (value < 0) {
sign = 0x4000;
value *= -1;
}
int expo;
double fract = frexp(value, &expo);
fract = frexp(value, &expo);
fract = ldexp(fract, 63);
mant = fract;
expo -= 63;
int vexp = expo + 0x1000;
vexp = expo + 0x1000;
assert(vexp >= 0);
assert(vexp < 0x2000);
vexp += sign;
@ -1085,9 +1086,11 @@ static const char* draw_lpm_output_delay(ivl_lpm_t net)
static void draw_lpm_abs(ivl_lpm_t net)
{
const char*src_table[1];
const char*dly;
draw_lpm_data_inputs(net, 0, 1, src_table);
const char*dly = draw_lpm_output_delay(net);
dly = draw_lpm_output_delay(net);
fprintf(vvp_out, "L_%p%s .abs %s;\n",
net, dly, src_table[0]);
@ -1096,9 +1099,11 @@ static void draw_lpm_abs(ivl_lpm_t net)
static void draw_lpm_cast_int(ivl_lpm_t net)
{
const char*src_table[1];
const char*dly;
draw_lpm_data_inputs(net, 0, 1, src_table);
const char*dly = draw_lpm_output_delay(net);
dly = draw_lpm_output_delay(net);
fprintf(vvp_out, "L_%p%s .cast/int %u, %s;\n",
net, dly, ivl_lpm_width(net), src_table[0]);
@ -1107,11 +1112,13 @@ static void draw_lpm_cast_int(ivl_lpm_t net)
static void draw_lpm_cast_real(ivl_lpm_t net)
{
const char*src_table[1];
const char*dly;
const char*is_signed = "";
draw_lpm_data_inputs(net, 0, 1, src_table);
const char*dly = draw_lpm_output_delay(net);
dly = draw_lpm_output_delay(net);
const char*is_signed = "";
if (ivl_lpm_signed(net)) is_signed = ".s";
fprintf(vvp_out, "L_%p%s .cast/real%s %s;\n",
@ -1126,6 +1133,7 @@ static void draw_lpm_add(ivl_lpm_t net)
ivl_variable_type_t dta = data_type_of_nexus(ivl_lpm_data(net,0));
ivl_variable_type_t dtb = data_type_of_nexus(ivl_lpm_data(net,1));
ivl_variable_type_t dto = IVL_VT_LOGIC;
const char*dly;
if (dta == IVL_VT_REAL || dtb == IVL_VT_REAL)
dto = IVL_VT_REAL;
@ -1179,7 +1187,7 @@ static void draw_lpm_add(ivl_lpm_t net)
draw_lpm_data_inputs(net, 0, 2, src_table);
const char*dly = draw_lpm_output_delay(net);
dly = draw_lpm_output_delay(net);
fprintf(vvp_out, "L_%p%s .arith/%s %u, %s, %s;\n",
net, dly, type, width, src_table[0], src_table[1]);
@ -1193,8 +1201,10 @@ static void draw_lpm_array(ivl_lpm_t net)
{
ivl_nexus_t nex;
ivl_signal_t mem = ivl_lpm_array(net);
const char*tmp;
nex = ivl_lpm_select(net);
const char*tmp = draw_net_input(nex);
tmp = draw_net_input(nex);
fprintf(vvp_out, "L_%p .array/port v%p, %s;\n", net, mem, tmp);
}
@ -1208,6 +1218,7 @@ static void draw_lpm_cmp(ivl_lpm_t net)
ivl_variable_type_t dta = data_type_of_nexus(ivl_lpm_data(net,0));
ivl_variable_type_t dtb = data_type_of_nexus(ivl_lpm_data(net,1));
ivl_variable_type_t dtc = IVL_VT_LOGIC;
const char*dly;
if (dta == IVL_VT_REAL || dtb == IVL_VT_REAL)
dtc = IVL_VT_REAL;
@ -1259,7 +1270,7 @@ static void draw_lpm_cmp(ivl_lpm_t net)
draw_lpm_data_inputs(net, 0, 2, src_table);
const char*dly = draw_lpm_output_delay(net);
dly = draw_lpm_output_delay(net);
fprintf(vvp_out, "L_%p%s .cmp/%s%s %u, %s, %s;\n",
net, dly, type, signed_string, width,
@ -1581,7 +1592,7 @@ static void draw_lpm_ufunc(ivl_lpm_t net)
fprintf(vvp_out, ")");
/* Finally, print the reference to the signal from which the
/* Now print the reference to the signal from which the
result is collected. */
{ ivl_signal_t psig = ivl_scope_port(def, 0);
assert(ivl_lpm_width(net) == ivl_signal_width(psig));
@ -1590,7 +1601,8 @@ static void draw_lpm_ufunc(ivl_lpm_t net)
fprintf(vvp_out, " v%p_0", psig);
}
fprintf(vvp_out, ";\n");
/* Finally, print the scope identifier. */
fprintf(vvp_out, " S_%p;\n", def);
}
/*
@ -1650,15 +1662,19 @@ static void draw_lpm_re(ivl_lpm_t net, const char*type)
static void draw_lpm_repeat(ivl_lpm_t net)
{
fprintf(vvp_out, "L_%p .repeat %u, %u, %s;\n", net,
const char*dly = draw_lpm_output_delay(net);
fprintf(vvp_out, "L_%p%s .repeat %u, %u, %s;\n", net, dly,
ivl_lpm_width(net), ivl_lpm_size(net),
draw_net_input(ivl_lpm_data(net,0)));
}
static void draw_lpm_sign_ext(ivl_lpm_t net)
{
fprintf(vvp_out, "L_%p .extend/s %u, %s;\n",
net, ivl_lpm_width(net),
const char*dly = draw_lpm_output_delay(net);
fprintf(vvp_out, "L_%p%s .extend/s %u, %s;\n",
net, dly, ivl_lpm_width(net),
draw_net_input(ivl_lpm_data(net,0)));
}
@ -1770,13 +1786,9 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent)
{
unsigned idx;
const char *type;
/* For now we do not support automatic tasks or functions. */
if (ivl_scope_is_auto(net)) {
fprintf(stderr, "%s:%u: vvp-tgt sorry: automatic tasks/functions "
"are not supported!\n",
ivl_scope_def_file(net), ivl_scope_def_lineno(net));
exit(1);
}
const char*prefix = ivl_scope_is_auto(net) ? "auto" : "";
switch (ivl_scope_type(net)) {
case IVL_SCT_MODULE: type = "module"; break;
case IVL_SCT_FUNCTION: type = "function"; break;
@ -1787,8 +1799,8 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent)
default: type = "?"; assert(0);
}
fprintf(vvp_out, "S_%p .scope %s, \"%s\" \"%s\" %d %d",
net, type, vvp_mangle_name(ivl_scope_basename(net)),
fprintf(vvp_out, "S_%p .scope %s%s, \"%s\" \"%s\" %d %d",
net, prefix, type, vvp_mangle_name(ivl_scope_basename(net)),
ivl_scope_tname(net), ivl_file_table_index(ivl_scope_file(net)),
ivl_scope_lineno(net));

View File

@ -23,6 +23,22 @@
# include <iostream>
# include <cassert>
# include <math.h> // Needed to get pow for as_double().
# include <stdio.h> // Needed to get snprintf for as_string().
#if !defined(HAVE_LROUND)
/*
* If the system doesn't provide the lround function, then we provide
* it ourselves here. It is simply the nearest integer, rounded away
* from zero.
*/
extern "C" long int lround(double x)
{
if (x >= 0.0)
return (long)floor(x+0.5);
else
return (long)ceil(x-0.5);
}
#endif
static verinum::V add_with_carry(verinum::V l, verinum::V r, verinum::V&c);

View File

@ -143,8 +143,10 @@ static int lookup_keyword(const char*text)
*/
static void process_quoted_string(void)
{
char*endp;
yylval.string_val = strdup(yytext+1);
char*endp = yylval.string_val+strlen(yylval.string_val);
endp = yylval.string_val+strlen(yylval.string_val);
assert(endp[-1] == '"');
endp[-1] = 0;
}

View File

@ -29,9 +29,10 @@
*/
static unsigned is_numeric_obj(vpiHandle obj)
{
assert(obj);
unsigned rtn = 0;
assert(obj);
switch(vpi_get(vpiType, obj)) {
case vpiConstant:
case vpiParameter:
@ -60,10 +61,11 @@ static unsigned is_numeric_obj(vpiHandle obj)
static PLI_INT32 sys_clog2_compiletf(PLI_BYTE8 *name)
{
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv, arg;
assert(callh != 0);
vpiHandle argv = vpi_iterate(vpiArgument, callh);
vpiHandle arg;
(void) name; // Not used!
argv = vpi_iterate(vpiArgument, callh);
(void) name; /* Not used! */
/* We must have an argument. */
if (argv == 0) {
@ -86,11 +88,13 @@ static PLI_INT32 sys_clog2_compiletf(PLI_BYTE8 *name)
/* We can have a maximum of one argument. */
if (vpi_scan(argv) != 0) {
char msg [64];
unsigned argc;
snprintf(msg, 64, "ERROR: %s line %d:",
vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh));
unsigned argc = 1;
argc = 1;
while (vpi_scan(argv)) argc += 1;
vpi_printf("%s $clog2 takes at most one argument.\n", msg);
@ -109,7 +113,7 @@ static PLI_INT32 sys_clog2_calltf(PLI_BYTE8 *name)
vpiHandle arg;
s_vpi_value val;
s_vpi_vecval vec;
(void) name; // Not used!/
(void) name; /* Not used! */
/* Get the argument. */
arg = vpi_scan(argv);

View File

@ -60,29 +60,30 @@ struct strobe_cb_info {
unsigned mcd;
};
// The number of decimal digits needed to represent a
// nr_bits binary number is floor(nr_bits*log_10(2))+1,
// where log_10(2) = 0.30102999566398.... and I approximate
// this transcendental number as 146/485, to avoid the vagaries
// of floating-point. The smallest nr_bits for which this
// approximation fails is 2621,
// 2621*log_10(2)=789.9996, but (2621*146+484)/485=790 (exactly).
// In cases like this, all that happens is we allocate one
// unneeded char for the output. I add a "L" suffix to 146
// to make sure the computation is done as long ints, otherwise
// on a 16-bit int machine (allowed by ISO C) we would mangle
// this computation for bit-length of 224. I'd like to put
// in a test for nr_bits < LONG_MAX/146, but don't know how
// to fail, other than crashing.
//
// In an April 2000 thread in comp.unix.programmer, with subject
// "integer -> string", I <LRDoolittle@lbl.gov> give the 28/93
// approximation, but overstate its accuracy: that version first
// fails when the number of bits is 289, not 671.
//
// This result does not include space for a trailing '\0', if any.
//
inline static int calc_dec_size(int nr_bits, int is_signed)
/*
* The number of decimal digits needed to represent a
* nr_bits binary number is floor(nr_bits*log_10(2))+1,
* where log_10(2) = 0.30102999566398.... and I approximate
* this transcendental number as 146/485, to avoid the vagaries
* of floating-point. The smallest nr_bits for which this
* approximation fails is 2621,
* 2621*log_10(2)=789.9996, but (2621*146+484)/485=790 (exactly).
* In cases like this, all that happens is we allocate one
* unneeded char for the output. I add a "L" suffix to 146
* to make sure the computation is done as long ints, otherwise
* on a 16-bit int machine (allowed by ISO C) we would mangle
* this computation for bit-length of 224. I'd like to put
* in a test for nr_bits < LONG_MAX/146, but don't know how
* to fail, other than crashing.
*
* In an April 2000 thread in comp.unix.programmer, with subject
* "integer -> string", I <LRDoolittle@lbl.gov> give the 28/93
* approximation, but overstate its accuracy: that version first
* fails when the number of bits is 289, not 671.
*
* This result does not include space for a trailing '\0', if any.
*/
__inline__ static int calc_dec_size(int nr_bits, int is_signed)
{
int r;
if (is_signed) --nr_bits;
@ -378,7 +379,7 @@ static int format_str_char(vpiHandle scope, unsigned int mcd,
use_count = 0;
break;
// new Verilog 2001 format specifiers...
/* new Verilog 2001 format specifiers... */
case 'l':
case 'L':
case 'u':
@ -445,7 +446,7 @@ static int format_str_char(vpiHandle scope, unsigned int mcd,
{ char* value_str = value.value.str;
if (leading_zero==1){
// Strip away all leading zeros from string
/* Strip away all leading zeros from string */
unsigned int i=0;
while(i< (strlen(value_str)-1) && value_str[i]=='0')
i++;
@ -511,11 +512,12 @@ static int format_str_char(vpiHandle scope, unsigned int mcd,
}
if (fsize==-1){
// simple %d parameter, or %0d parameter.
// Size is now determined by the width
// of the vector or integer. If %0d, then
// set the size to 0 so that the minimum
// size is used.
/* simple %d parameter, or %0d parameter.
* Size is now determined by the width
* of the vector or integer. If %0d, then
* set the size to 0 so that the minimum
* size is used.
*/
fsize = (leading_zero==1)
? 0
: vpi_get_dec_size(argv[idx]);
@ -871,7 +873,7 @@ static int get_default_format(char *name)
int default_format;
switch(name[ strlen(name)-1 ]){
// writE/strobE or monitoR or displaY/fdisplaY or sformaT
/* writE/strobE or monitoR or displaY/fdisplaY or sformaT */
case 'e':
case 'r':
case 't':
@ -1938,7 +1940,7 @@ static PLI_INT32 sys_swrite_compiletf(PLI_BYTE8 *name)
}
/* The first argument must be a register. */
reg = vpi_scan(argv); //* This should never be zero. */
reg = vpi_scan(argv); /* This should never be zero. */
if (vpi_get(vpiType, reg) != vpiReg) {
vpi_printf("ERROR: %s's first argument must be a register.\n", name);
vpi_control(vpiFinish, 1);
@ -1998,7 +2000,7 @@ static PLI_INT32 sys_sformat_compiletf(PLI_BYTE8 *name)
}
/* The first argument must be a register. */
arg = vpi_scan(argv); //* This should never be zero. */
arg = vpi_scan(argv); /* This should never be zero. */
if (vpi_get(vpiType, arg) != vpiReg) {
vpi_printf("ERROR: %s's first argument must be a register.\n", name);
vpi_control(vpiFinish, 1);
@ -2201,7 +2203,7 @@ void sys_display_register()
s_cb_data cb_data;
s_vpi_systf_data tf_data;
//============================== display
/*============================== display */
tf_data.type = vpiSysTask;
tf_data.tfname = "$display";
tf_data.calltf = sys_display_calltf;
@ -2234,7 +2236,7 @@ void sys_display_register()
tf_data.user_data = "$displayb";
vpi_register_systf(&tf_data);
//============================== write
/*============================== write */
tf_data.type = vpiSysTask;
tf_data.tfname = "$write";
tf_data.calltf = sys_display_calltf;
@ -2267,7 +2269,7 @@ void sys_display_register()
tf_data.user_data = "$writeb";
vpi_register_systf(&tf_data);
//============================== strobe
/*============================== strobe */
tf_data.type = vpiSysTask;
tf_data.tfname = "$strobe";
tf_data.calltf = sys_strobe_calltf;
@ -2300,7 +2302,7 @@ void sys_display_register()
tf_data.user_data = "$strobeb";
vpi_register_systf(&tf_data);
//============================== fstrobe
/*============================== fstrobe */
tf_data.type = vpiSysTask;
tf_data.tfname = "$fstrobe";
tf_data.calltf = sys_strobe_calltf;
@ -2333,7 +2335,7 @@ void sys_display_register()
tf_data.user_data = "$fstrobeb";
vpi_register_systf(&tf_data);
//============================== monitor
/*============================== monitor */
tf_data.type = vpiSysTask;
tf_data.tfname = "$monitor";
tf_data.calltf = sys_monitor_calltf;
@ -2382,7 +2384,7 @@ void sys_display_register()
tf_data.user_data = "$monitoroff";
vpi_register_systf(&tf_data);
//============================== fdisplay
/*============================== fdisplay */
tf_data.type = vpiSysTask;
tf_data.tfname = "$fdisplay";
tf_data.calltf = sys_fdisplay_calltf;
@ -2415,7 +2417,7 @@ void sys_display_register()
tf_data.user_data = "$fdisplayb";
vpi_register_systf(&tf_data);
//============================== fwrite
/*============================== fwrite */
tf_data.type = vpiSysTask;
tf_data.tfname = "$fwrite";
tf_data.calltf = sys_fdisplay_calltf;
@ -2448,7 +2450,7 @@ void sys_display_register()
tf_data.user_data = "$fwriteb";
vpi_register_systf(&tf_data);
//============================== swrite
/*============================== swrite */
tf_data.type = vpiSysTask;
tf_data.tfname = "$swrite";
tf_data.calltf = sys_swrite_calltf;
@ -2489,7 +2491,7 @@ void sys_display_register()
tf_data.user_data = "$sformat";
vpi_register_systf(&tf_data);
//============================ timeformat
/*============================ timeformat */
tf_data.type = vpiSysTask;
tf_data.tfname = "$timeformat";
tf_data.calltf = sys_timeformat_calltf;

View File

@ -34,9 +34,10 @@
static PLI_INT32 sys_fopen_compiletf(PLI_BYTE8 *name)
{
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
assert(callh != 0);
vpiHandle argv = vpi_iterate(vpiArgument, callh);
vpiHandle argv;
vpiHandle arg;
assert(callh != 0);
argv = vpi_iterate(vpiArgument, callh);
/* Check that there is a file name argument and that it is a string. */
if (argv == 0) {
@ -68,11 +69,13 @@ static PLI_INT32 sys_fopen_compiletf(PLI_BYTE8 *name)
/* Make sure there are no extra arguments. */
if (vpi_scan(argv) != 0) {
char msg [64];
unsigned argc;
snprintf(msg, 64, "ERROR: %s line %d:",
vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh));
unsigned argc = 1;
argc = 1;
while (vpi_scan(argv)) argc += 1;
vpi_printf("%s %s takes at most two string arguments.\n",
@ -95,6 +98,7 @@ static PLI_INT32 sys_fopen_calltf(PLI_BYTE8*name)
unsigned idx;
vpiHandle item = vpi_scan(argv);
vpiHandle mode = vpi_scan(argv);
unsigned len;
/* Get the mode handle if it exists. */
if (mode) {
@ -177,7 +181,7 @@ static PLI_INT32 sys_fopen_calltf(PLI_BYTE8*name)
* Verify that the file name is composed of only printable
* characters.
*/
unsigned len = strlen(val.value.str);
len = strlen(val.value.str);
for (idx = 0; idx < len; idx++) {
if (! isprint(val.value.str[idx])) {
char msg [64];
@ -217,10 +221,11 @@ static PLI_INT32 sys_fopenrwa_calltf(PLI_BYTE8*name)
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv = vpi_iterate(vpiArgument, callh);
vpiHandle file = vpi_scan(argv);
vpi_free_object(argv);
s_vpi_value val;
char *mode;
unsigned idx, len;
vpi_free_object(argv);
/* Get the mode. */
mode = name + strlen(name) - 1;
@ -242,7 +247,7 @@ static PLI_INT32 sys_fopenrwa_calltf(PLI_BYTE8*name)
* Verify that the file name is composed of only printable
* characters.
*/
unsigned idx, len = strlen(val.value.str);
len = strlen(val.value.str);
for (idx = 0; idx < len; idx++) {
if (! isprint(val.value.str[idx])) {
char msg [64];
@ -272,12 +277,12 @@ static PLI_INT32 sys_fclose_calltf(PLI_BYTE8*name)
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv = vpi_iterate(vpiArgument, callh);
vpiHandle fd = vpi_scan(argv);
vpi_free_object(argv);
(void) name; /* Not used! */
s_vpi_value val;
PLI_UINT32 fd_mcd;
vpi_free_object(argv);
(void) name; /* Not used! */
val.format = vpiIntVal;
vpi_get_value(fd, &val);
fd_mcd = val.value.integer;
@ -406,11 +411,13 @@ static PLI_INT32 sys_fgets_compiletf(PLI_BYTE8*name)
/* Make sure there are no extra arguments. */
if (vpi_scan(argv) != 0) {
char msg [64];
unsigned argc;
snprintf(msg, 64, "ERROR: %s line %d:",
vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh));
unsigned argc = 1;
argc = 1;
while (vpi_scan(argv)) argc += 1;
vpi_printf("%s %s takes two arguments.\n", msg, name);
@ -590,11 +597,13 @@ static PLI_INT32 sys_fseek_compiletf(PLI_BYTE8*name)
/* Make sure there are no extra arguments. */
if (vpi_scan(argv) != 0) {
char msg [64];
unsigned argc;
snprintf(msg, 64, "ERROR: %s line %d:",
vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh));
unsigned argc = 1;
argc = 1;
while (vpi_scan(argv)) argc += 1;
vpi_printf("%s %s takes three arguments.\n", msg, name);
@ -727,7 +736,7 @@ void sys_fileio_register()
{
s_vpi_systf_data tf_data;
//============================== fopen
/*============================== fopen */
tf_data.type = vpiSysFunc;
tf_data.sysfunctype = vpiIntFunc;
tf_data.tfname = "$fopen";
@ -737,7 +746,7 @@ void sys_fileio_register()
tf_data.user_data = "$fopen";
vpi_register_systf(&tf_data);
//============================== fopenr
/*============================== fopenr */
tf_data.type = vpiSysFunc;
tf_data.sysfunctype = vpiIntFunc;
tf_data.tfname = "$fopenr";
@ -747,17 +756,17 @@ void sys_fileio_register()
tf_data.user_data = "$fopenr";
vpi_register_systf(&tf_data);
//============================== fopenw
/*============================== fopenw */
tf_data.tfname = "$fopenw";
tf_data.user_data = "$fopenw";
vpi_register_systf(&tf_data);
//============================== fopena
/*============================== fopena */
tf_data.tfname = "$fopena";
tf_data.user_data = "$fopena";
vpi_register_systf(&tf_data);
//============================== fclose
/*============================== fclose */
tf_data.type = vpiSysTask;
tf_data.tfname = "$fclose";
tf_data.calltf = sys_fclose_calltf;
@ -766,7 +775,7 @@ void sys_fileio_register()
tf_data.user_data = "$fclose";
vpi_register_systf(&tf_data);
//============================== fflush
/*============================== fflush */
tf_data.type = vpiSysTask;
tf_data.tfname = "$fflush";
tf_data.calltf = sys_fflush_calltf;
@ -775,7 +784,7 @@ void sys_fileio_register()
tf_data.user_data = "$fflush";
vpi_register_systf(&tf_data);
//============================== fputc
/*============================== fputc */
tf_data.type = vpiSysTask;
tf_data.tfname = "$fputc";
tf_data.calltf = sys_fputc_calltf;
@ -784,7 +793,7 @@ void sys_fileio_register()
tf_data.user_data = "$fputc";
vpi_register_systf(&tf_data);
//============================== fgetc
/*============================== fgetc */
tf_data.type = vpiSysFunc;
tf_data.sysfunctype = vpiIntFunc;
tf_data.tfname = "$fgetc";
@ -794,7 +803,7 @@ void sys_fileio_register()
tf_data.user_data = "$fgetc";
vpi_register_systf(&tf_data);
//============================== fgets
/*============================== fgets */
tf_data.type = vpiSysFunc;
tf_data.sysfunctype = vpiIntFunc;
tf_data.tfname = "$fgets";
@ -804,7 +813,7 @@ void sys_fileio_register()
tf_data.user_data = "$fgets";
vpi_register_systf(&tf_data);
//============================== ungetc
/*============================== ungetc */
tf_data.type = vpiSysFunc;
tf_data.sysfunctype = vpiIntFunc;
tf_data.tfname = "$ungetc";
@ -814,7 +823,7 @@ void sys_fileio_register()
tf_data.user_data = "$ungetc";
vpi_register_systf(&tf_data);
//============================== ftell
/*============================== ftell */
tf_data.type = vpiSysFunc;
tf_data.sysfunctype = vpiIntFunc;
tf_data.tfname = "$ftell";
@ -824,7 +833,7 @@ void sys_fileio_register()
tf_data.user_data = "$ftell";
vpi_register_systf(&tf_data);
//============================== fseek
/*============================== fseek */
tf_data.type = vpiSysFunc;
tf_data.sysfunctype = vpiIntFunc;
tf_data.tfname = "$fseek";
@ -834,7 +843,7 @@ void sys_fileio_register()
tf_data.user_data = "$fseek";
vpi_register_systf(&tf_data);
//============================== rewind
/*============================== rewind */
tf_data.type = vpiSysFunc;
tf_data.sysfunctype = vpiIntFunc;
tf_data.tfname = "$rewind";
@ -845,7 +854,7 @@ void sys_fileio_register()
vpi_register_systf(&tf_data);
/* $feof() is from 1364-2005. */
//============================== feof
/*============================== feof */
tf_data.type = vpiSysFunc;
tf_data.sysfunctype = vpiIntFunc;
tf_data.tfname = "$feof";

View File

@ -202,7 +202,7 @@ struct vcd_names_list_s lxt_tab;
static int dumpvars_status = 0; /* 0:fresh 1:cb installed, 2:callback done */
static PLI_UINT64 dumpvars_time;
inline static int dump_header_pending(void)
__inline__ static int dump_header_pending(void)
{
return dumpvars_status != 2;
}
@ -312,7 +312,7 @@ static PLI_INT32 finish_cb(p_cb_data cause)
return 0;
}
inline static int install_dumpvars_callback(void)
__inline__ static int install_dumpvars_callback(void)
{
struct t_cb_data cb;
static struct t_vpi_time time;
@ -712,7 +712,7 @@ static PLI_INT32 sys_dumpvars_calltf(PLI_BYTE8*name)
/* This dumps all the modules in the design if none are given. */
if (!argv || !(item = vpi_scan(argv))) {
argv = vpi_iterate(vpiModule, 0x0);
assert(argv); // There must be at least one top level module.
assert(argv); /* There must be at least one top level module. */
item = vpi_scan(argv);
}

View File

@ -204,7 +204,7 @@ struct vcd_names_list_s lxt_tab;
static int dumpvars_status = 0; /* 0:fresh 1:cb installed, 2:callback done */
static PLI_UINT64 dumpvars_time;
inline static int dump_header_pending(void)
__inline__ static int dump_header_pending(void)
{
return dumpvars_status != 2;
}
@ -311,7 +311,7 @@ static PLI_INT32 finish_cb(p_cb_data cause)
return 0;
}
inline static int install_dumpvars_callback(void)
__inline__ static int install_dumpvars_callback(void)
{
struct t_cb_data cb;
static struct t_vpi_time time;
@ -724,7 +724,7 @@ static PLI_INT32 sys_dumpvars_calltf(PLI_BYTE8*name)
/* This dumps all the modules in the design if none are given. */
if (!argv || !(item = vpi_scan(argv))) {
argv = vpi_iterate(vpiModule, 0x0);
assert(argv); // There must be at least one top level module.
assert(argv); /* There must be at least one top level module. */
item = vpi_scan(argv);
}

View File

@ -41,9 +41,10 @@ PLI_UINT64 timerec_to_time64(const struct t_vpi_time*time)
*/
unsigned is_constant_obj(vpiHandle obj)
{
assert(obj);
unsigned rtn = 0;
assert(obj);
switch(vpi_get(vpiType, obj)) {
case vpiConstant:
case vpiParameter:
@ -60,9 +61,10 @@ unsigned is_constant_obj(vpiHandle obj)
*/
unsigned is_numeric_obj(vpiHandle obj)
{
assert(obj);
unsigned rtn = 0;
assert(obj);
switch(vpi_get(vpiType, obj)) {
case vpiConstant:
case vpiParameter:
@ -92,9 +94,10 @@ unsigned is_numeric_obj(vpiHandle obj)
*/
unsigned is_string_obj(vpiHandle obj)
{
assert(obj);
unsigned rtn = 0;
assert(obj);
switch(vpi_get(vpiType, obj)) {
case vpiConstant:
case vpiParameter: {
@ -147,11 +150,13 @@ PLI_INT32 sys_no_arg_compiletf(PLI_BYTE8 *name)
/* Make sure there are no arguments. */
if (argv != 0) {
char msg [64];
unsigned argc;
snprintf(msg, 64, "ERROR: %s line %d:",
vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh));
unsigned argc = 0;
argc = 0;
while (vpi_scan(argv)) argc += 1;
vpi_printf("%s %s does not take an argument.\n", msg, name);
@ -188,11 +193,13 @@ PLI_INT32 sys_one_numeric_arg_compiletf(PLI_BYTE8 *name)
/* Make sure there are no extra arguments. */
if (vpi_scan(argv) != 0) {
char msg [64];
unsigned argc;
snprintf(msg, 64, "ERROR: %s line %d:",
vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh));
unsigned argc = 1;
argc = 1;
while (vpi_scan(argv)) argc += 1;
vpi_printf("%s %s takes a single numeric argument.\n", msg, name);
@ -223,11 +230,13 @@ PLI_INT32 sys_one_opt_numeric_arg_compiletf(PLI_BYTE8 *name)
/* Make sure there are no extra arguments. */
if (vpi_scan(argv) != 0) {
char msg [64];
unsigned argc;
snprintf(msg, 64, "ERROR: %s line %d:",
vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh));
unsigned argc = 1;
argc = 1;
while (vpi_scan(argv)) argc += 1;
vpi_printf("%s %s takes at most one numeric argument.\n",
@ -282,11 +291,13 @@ PLI_INT32 sys_two_numeric_args_compiletf(PLI_BYTE8 *name)
/* Make sure there are no extra arguments. */
if (vpi_scan(argv) != 0) {
char msg [64];
unsigned argc;
snprintf(msg, 64, "ERROR: %s line %d:",
vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh));
unsigned argc = 1;
argc = 1;
while (vpi_scan(argv)) argc += 1;
vpi_printf("%s %s takes two numeric arguments.\n", msg, name);
@ -322,11 +333,13 @@ PLI_INT32 sys_one_string_arg_compiletf(PLI_BYTE8 *name)
/* Make sure there are no extra arguments. */
if (vpi_scan(argv) != 0) {
char msg [64];
unsigned argc;
snprintf(msg, 64, "ERROR: %s line %d:",
vpi_get_str(vpiFile, callh),
(int)vpi_get(vpiLineNo, callh));
unsigned argc = 1;
argc = 1;
while (vpi_scan(argv)) argc += 1;
vpi_printf("%s %s takes a single string argument.\n", msg, name);

View File

@ -43,7 +43,7 @@ static struct context_s global_context = {
#if defined(__GCC__)
.mti =
#else
// For MSVC simply use the fact that mti is located first
/* For MSVC simply use the fact that mti is located first */
#endif
NP1 };

Some files were not shown because too many files have changed in this diff Show More