Merge branch 'master' of git://icarus.com/~steve-icarus/verilog into vhdl
Conflicts: tgt-vhdl/stmt.cc
This commit is contained in:
commit
4394aff909
27
Makefile.in
27
Makefile.in
|
|
@ -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
|
||||
|
|
|
|||
34
Module.h
34
Module.h
|
|
@ -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. */
|
||||
|
|
|
|||
10
PDelays.cc
10
PDelays.cc
|
|
@ -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
246
PExpr.h
|
|
@ -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
12
PGate.h
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
57
PScope.h
57
PScope.h
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -93,4 +93,4 @@
|
|||
* junk, and support gcc 3.0. (Stephan Boettcher)
|
||||
*
|
||||
*/
|
||||
#endif // __config_H
|
||||
#endif /* __config_H */
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
161
driver/main.c
161
driver/main.c
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
960
elab_expr.cc
960
elab_expr.cc
File diff suppressed because it is too large
Load Diff
3119
elab_net.cc
3119
elab_net.cc
File diff suppressed because it is too large
Load Diff
140
elab_pexpr.cc
140
elab_pexpr.cc
|
|
@ -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 "
|
||||
|
|
|
|||
245
elab_scope.cc
245
elab_scope.cc
|
|
@ -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>¶meters)
|
||||
{
|
||||
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>¶meters)
|
||||
{
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
1209
elaborate.cc
1209
elaborate.cc
File diff suppressed because it is too large
Load Diff
26
emit.cc
26
emit.cc
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
75
eval_tree.cc
75
eval_tree.cc
|
|
@ -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) {
|
||||
|
|
|
|||
504
expr_synth.cc
504
expr_synth.cc
|
|
@ -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 "
|
||||
|
|
|
|||
10
ivl_target.h
10
ivl_target.h
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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@
|
||||
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
}
|
||||
|
|
|
|||
25
ivlpp/main.c
25
ivlpp/main.c
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
34
lexor.lex
34
lexor.lex
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ PLI_INT32 acc_fetch_fulltype(handle obj)
|
|||
return accTopModule;
|
||||
else
|
||||
return accModuleInstance;
|
||||
// FIXME accCellInstance
|
||||
/* FIXME accCellInstance */
|
||||
|
||||
case vpiNamedEvent: return accNamedEvent;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
56
main.cc
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
|
|
|
|||
13
net_expr.cc
13
net_expr.cc
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
66
net_link.cc
66
net_link.cc
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
11
net_tran.cc
11
net_tran.cc
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
265
netlist.cc
265
netlist.cc
|
|
@ -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
146
netlist.h
|
|
@ -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
|
||||
|
|
|
|||
93
netmisc.cc
93
netmisc.cc
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
33
netmisc.h
33
netmisc.h
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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
17
parse.y
|
|
@ -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. */
|
||||
|
|
|
|||
63
pform.cc
63
pform.cc
|
|
@ -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;
|
||||
|
|
|
|||
4
pform.h
4
pform.h
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
175
pform_dump.cc
175
pform_dump.cc
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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: "
|
||||
|
|
|
|||
45
synth.cc
45
synth.cc
|
|
@ -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.
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
21
t-dll-api.cc
21
t-dll-api.cc
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
117
t-dll-proc.cc
117
t-dll-proc.cc
|
|
@ -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*)
|
||||
|
|
|
|||
46
t-dll.cc
46
t-dll.cc
|
|
@ -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
23
t-dll.h
|
|
@ -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_;
|
||||
|
|
|
|||
12
target.cc
12
target.cc
|
|
@ -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: "
|
||||
|
|
|
|||
11
target.h
11
target.h
|
|
@ -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
|
||||
|
|
|
|||
29
targets.cc
29
targets.cc
|
|
@ -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
|
||||
};
|
||||
|
|
@ -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@
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
functor:synth2
|
||||
functor:synth
|
||||
functor:syn-rules
|
||||
-t:dll
|
||||
flag:DLL=null.tgt
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,2 +1 @@
|
|||
-t:dll
|
||||
flag:DLL=null.tgt
|
||||
|
|
|
|||
|
|
@ -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@
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,5 +3,4 @@ functor:synth
|
|||
functor:syn-rules
|
||||
functor:cprop
|
||||
functor:nodangle
|
||||
-t:dll
|
||||
flag:DLL=stub.tgt
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
functor:cprop
|
||||
functor:nodangle
|
||||
-t:dll
|
||||
flag:DLL=stub.tgt
|
||||
|
|
|
|||
|
|
@ -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. */
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
functor:cprop
|
||||
functor:nodangle
|
||||
-t:dll
|
||||
flag:DLL=vhdl.tgt
|
||||
|
|
|
|||
|
|
@ -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_);
|
||||
|
|
|
|||
|
|
@ -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@
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -3,5 +3,4 @@ functor:synth
|
|||
functor:syn-rules
|
||||
functor:cprop
|
||||
functor:nodangle
|
||||
-t:dll
|
||||
flag:DLL=vvp.tgt
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
functor:cprop
|
||||
functor:nodangle
|
||||
-t:dll
|
||||
flag:DLL=vvp.tgt
|
||||
|
|
|
|||
|
|
@ -46,4 +46,4 @@
|
|||
* Isolate configure from containing config.h
|
||||
*
|
||||
*/
|
||||
#endif // __vvp_config_H
|
||||
#endif /* __vvp_config_H */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
||||
|
|
|
|||
16
verinum.cc
16
verinum.cc
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
Loading…
Reference in New Issue