Merge branch 'v10-branch' of github.com:steveicarus/iverilog into v10-branch
This commit is contained in:
commit
5e41c86d01
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1998-2010 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 1998-2016 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -35,9 +35,6 @@ Module::Module(LexicalScope*parent, perm_string n)
|
||||||
program_block = false;
|
program_block = false;
|
||||||
uc_drive = UCD_NONE;
|
uc_drive = UCD_NONE;
|
||||||
timescale_warn_done = false;
|
timescale_warn_done = false;
|
||||||
time_unit = 0;
|
|
||||||
time_precision = 0;
|
|
||||||
time_from_timescale = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Module::~Module()
|
Module::~Module()
|
||||||
|
|
|
||||||
6
Module.h
6
Module.h
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef IVL_Module_H
|
#ifndef IVL_Module_H
|
||||||
#define IVL_Module_H
|
#define IVL_Module_H
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1998-2015 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 1998-2016 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -121,10 +121,6 @@ class Module : public PScopeExtra, public LineInfo {
|
||||||
|
|
||||||
map<perm_string,PExpr*> attributes;
|
map<perm_string,PExpr*> attributes;
|
||||||
|
|
||||||
/* These are the timescale for this module. The default is
|
|
||||||
set by the `timescale directive. */
|
|
||||||
int time_unit, time_precision;
|
|
||||||
bool time_from_timescale;
|
|
||||||
bool timescale_warn_done;
|
bool timescale_warn_done;
|
||||||
|
|
||||||
/* The module has a list of generate schemes that appear in
|
/* The module has a list of generate schemes that appear in
|
||||||
|
|
|
||||||
4
PExpr.cc
4
PExpr.cc
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1998-2012 Stephen Williams <steve@icarus.com>
|
* Copyright (c) 1998-2016 Stephen Williams <steve@icarus.com>
|
||||||
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
|
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
|
|
@ -137,7 +137,7 @@ bool PEBinary::has_aa_term(Design*des, NetScope*scope) const
|
||||||
return left_->has_aa_term(des, scope) || right_->has_aa_term(des, scope);
|
return left_->has_aa_term(des, scope) || right_->has_aa_term(des, scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
PECastSize::PECastSize(unsigned si, PExpr*b)
|
PECastSize::PECastSize(PExpr*si, PExpr*b)
|
||||||
: size_(si), base_(b)
|
: size_(si), base_(b)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
||||||
6
PExpr.h
6
PExpr.h
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef IVL_PExpr_H
|
#ifndef IVL_PExpr_H
|
||||||
#define IVL_PExpr_H
|
#define IVL_PExpr_H
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1998-2014 Stephen Williams <steve@icarus.com>
|
* Copyright (c) 1998-2016 Stephen Williams <steve@icarus.com>
|
||||||
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
|
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
|
|
@ -971,7 +971,7 @@ class PECallFunction : public PExpr {
|
||||||
class PECastSize : public PExpr {
|
class PECastSize : public PExpr {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit PECastSize(unsigned expr_wid, PExpr*base);
|
explicit PECastSize(PExpr*size, PExpr*base);
|
||||||
~PECastSize();
|
~PECastSize();
|
||||||
|
|
||||||
void dump(ostream &out) const;
|
void dump(ostream &out) const;
|
||||||
|
|
@ -984,7 +984,7 @@ class PECastSize : public PExpr {
|
||||||
width_mode_t&mode);
|
width_mode_t&mode);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
unsigned size_;
|
PExpr* size_;
|
||||||
PExpr* base_;
|
PExpr* base_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
37
PScope.cc
37
PScope.cc
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008,2010 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2008,2016 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -19,21 +19,9 @@
|
||||||
|
|
||||||
# include "PScope.h"
|
# include "PScope.h"
|
||||||
|
|
||||||
PScope::PScope(perm_string n, LexicalScope*parent)
|
bool LexicalScope::var_init_needs_explicit_lifetime() const
|
||||||
: LexicalScope(parent), name_(n)
|
|
||||||
{
|
{
|
||||||
}
|
return false;
|
||||||
|
|
||||||
PScope::PScope(perm_string n)
|
|
||||||
: LexicalScope(0), name_(n)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
PScope::~PScope()
|
|
||||||
{
|
|
||||||
for(map<perm_string, data_type_t*>::iterator it = typedefs.begin();
|
|
||||||
it != typedefs.end(); ++it)
|
|
||||||
delete it->second;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PWire* LexicalScope::wires_find(perm_string name)
|
PWire* LexicalScope::wires_find(perm_string name)
|
||||||
|
|
@ -45,17 +33,26 @@ PWire* LexicalScope::wires_find(perm_string name)
|
||||||
return (*cur).second;
|
return (*cur).second;
|
||||||
}
|
}
|
||||||
|
|
||||||
PScopeExtra::PScopeExtra(perm_string n, LexicalScope*parent)
|
PScope::PScope(perm_string n, LexicalScope*parent)
|
||||||
: PScope(n, parent)
|
: LexicalScope(parent), name_(n)
|
||||||
{
|
{
|
||||||
|
time_unit = 0;
|
||||||
|
time_precision = 0;
|
||||||
|
time_from_timescale = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
PScopeExtra::PScopeExtra(perm_string n)
|
PScope::~PScope()
|
||||||
: PScope(n)
|
{
|
||||||
|
for(map<perm_string, data_type_t*>::iterator it = typedefs.begin();
|
||||||
|
it != typedefs.end(); ++it)
|
||||||
|
delete it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
PScopeExtra::PScopeExtra(perm_string n, LexicalScope*parent)
|
||||||
|
: PScope(n, parent)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
PScopeExtra::~PScopeExtra()
|
PScopeExtra::~PScopeExtra()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
32
PScope.h
32
PScope.h
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef IVL_PScope_H
|
#ifndef IVL_PScope_H
|
||||||
#define IVL_PScope_H
|
#define IVL_PScope_H
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008-2014 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2008-2016 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -36,6 +36,7 @@ class PProcess;
|
||||||
class PClass;
|
class PClass;
|
||||||
class PTask;
|
class PTask;
|
||||||
class PWire;
|
class PWire;
|
||||||
|
class Statement;
|
||||||
|
|
||||||
class Design;
|
class Design;
|
||||||
class NetScope;
|
class NetScope;
|
||||||
|
|
@ -52,10 +53,14 @@ class NetScope;
|
||||||
class LexicalScope {
|
class LexicalScope {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit LexicalScope(LexicalScope*parent) : parent_(parent) { }
|
enum lifetime_t { INHERITED, STATIC, AUTOMATIC };
|
||||||
|
|
||||||
|
explicit LexicalScope(LexicalScope*parent) : default_lifetime(INHERITED), parent_(parent) { }
|
||||||
// A virtual destructor is so that dynamic_cast can work.
|
// A virtual destructor is so that dynamic_cast can work.
|
||||||
virtual ~LexicalScope() { }
|
virtual ~LexicalScope() { }
|
||||||
|
|
||||||
|
lifetime_t default_lifetime;
|
||||||
|
|
||||||
struct range_t {
|
struct range_t {
|
||||||
// True if this is an exclude
|
// True if this is an exclude
|
||||||
bool exclude_flag;
|
bool exclude_flag;
|
||||||
|
|
@ -108,6 +113,9 @@ class LexicalScope {
|
||||||
// creating implicit nets.
|
// creating implicit nets.
|
||||||
map<perm_string,LineInfo*> genvars;
|
map<perm_string,LineInfo*> genvars;
|
||||||
|
|
||||||
|
// Variable initializations in this scope
|
||||||
|
vector<Statement*> var_inits;
|
||||||
|
|
||||||
// Behaviors (processes) in this scope
|
// Behaviors (processes) in this scope
|
||||||
list<PProcess*> behaviors;
|
list<PProcess*> behaviors;
|
||||||
list<AProcess*> analog_behaviors;
|
list<AProcess*> analog_behaviors;
|
||||||
|
|
@ -117,6 +125,8 @@ class LexicalScope {
|
||||||
|
|
||||||
LexicalScope* parent_scope() const { return parent_; }
|
LexicalScope* parent_scope() const { return parent_; }
|
||||||
|
|
||||||
|
virtual bool var_init_needs_explicit_lifetime() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void dump_typedefs_(ostream&out, unsigned indent) const;
|
void dump_typedefs_(ostream&out, unsigned indent) const;
|
||||||
|
|
||||||
|
|
@ -130,6 +140,10 @@ class LexicalScope {
|
||||||
|
|
||||||
void dump_wires_(ostream&out, unsigned indent) const;
|
void dump_wires_(ostream&out, unsigned indent) const;
|
||||||
|
|
||||||
|
void dump_var_inits_(ostream&out, unsigned indent) const;
|
||||||
|
|
||||||
|
bool elaborate_var_inits_(Design*des, NetScope*scope) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
LexicalScope*parent_;
|
LexicalScope*parent_;
|
||||||
};
|
};
|
||||||
|
|
@ -145,12 +159,17 @@ class PScope : public LexicalScope {
|
||||||
// modules do not nest in Verilog, the parent must be nil for
|
// modules do not nest in Verilog, the parent must be nil for
|
||||||
// modules. Scopes for tasks and functions point to their
|
// modules. Scopes for tasks and functions point to their
|
||||||
// containing module.
|
// containing module.
|
||||||
PScope(perm_string name, LexicalScope*parent);
|
explicit PScope(perm_string name, LexicalScope*parent =0);
|
||||||
PScope(perm_string name);
|
|
||||||
virtual ~PScope();
|
virtual ~PScope();
|
||||||
|
|
||||||
perm_string pscope_name() const { return name_; }
|
perm_string pscope_name() const { return name_; }
|
||||||
|
|
||||||
|
/* These are the timescale for this scope. The default is
|
||||||
|
set by the `timescale directive or, in SystemVerilog,
|
||||||
|
by timeunit and timeprecision statements. */
|
||||||
|
int time_unit, time_precision;
|
||||||
|
bool time_from_timescale;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool elaborate_sig_wires_(Design*des, NetScope*scope) const;
|
bool elaborate_sig_wires_(Design*des, NetScope*scope) const;
|
||||||
|
|
||||||
|
|
@ -168,14 +187,13 @@ class PScope : public LexicalScope {
|
||||||
class PScopeExtra : public PScope {
|
class PScopeExtra : public PScope {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PScopeExtra(perm_string, LexicalScope*parent);
|
explicit PScopeExtra(perm_string, LexicalScope*parent =0);
|
||||||
PScopeExtra(perm_string);
|
|
||||||
~PScopeExtra();
|
~PScopeExtra();
|
||||||
|
|
||||||
/* Task definitions within this module */
|
/* Task definitions within this module */
|
||||||
std::map<perm_string,PTask*> tasks;
|
std::map<perm_string,PTask*> tasks;
|
||||||
std::map<perm_string,PFunction*> funcs;
|
std::map<perm_string,PFunction*> funcs;
|
||||||
/* class definitions within this module. */
|
/* Class definitions within this module. */
|
||||||
std::map<perm_string,PClass*> classes;
|
std::map<perm_string,PClass*> classes;
|
||||||
/* This is the lexical order of the classes, and is used by
|
/* This is the lexical order of the classes, and is used by
|
||||||
elaboration to choose an elaboration order. */
|
elaboration to choose an elaboration order. */
|
||||||
|
|
|
||||||
5
PTask.cc
5
PTask.cc
|
|
@ -30,6 +30,11 @@ PTaskFunc::~PTaskFunc()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PTaskFunc::var_init_needs_explicit_lifetime() const
|
||||||
|
{
|
||||||
|
return default_lifetime == STATIC;
|
||||||
|
}
|
||||||
|
|
||||||
void PTaskFunc::set_ports(vector<pform_tf_port_t>*p)
|
void PTaskFunc::set_ports(vector<pform_tf_port_t>*p)
|
||||||
{
|
{
|
||||||
assert(ports_ == 0);
|
assert(ports_ == 0);
|
||||||
|
|
|
||||||
2
PTask.h
2
PTask.h
|
|
@ -41,6 +41,8 @@ class PTaskFunc : public PScope, public LineInfo {
|
||||||
PTaskFunc(perm_string name, LexicalScope*parent);
|
PTaskFunc(perm_string name, LexicalScope*parent);
|
||||||
~PTaskFunc();
|
~PTaskFunc();
|
||||||
|
|
||||||
|
bool var_init_needs_explicit_lifetime() const;
|
||||||
|
|
||||||
void set_ports(std::vector<pform_tf_port_t>*p);
|
void set_ports(std::vector<pform_tf_port_t>*p);
|
||||||
|
|
||||||
void set_this(class_type_t*use_type, PWire*this_wire);
|
void set_this(class_type_t*use_type, PWire*this_wire);
|
||||||
|
|
|
||||||
|
|
@ -115,6 +115,11 @@ PBlock::~PBlock()
|
||||||
delete list_[idx];
|
delete list_[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PBlock::var_init_needs_explicit_lifetime() const
|
||||||
|
{
|
||||||
|
return default_lifetime == STATIC;
|
||||||
|
}
|
||||||
|
|
||||||
PChainConstructor* PBlock::extract_chain_constructor()
|
PChainConstructor* PBlock::extract_chain_constructor()
|
||||||
{
|
{
|
||||||
if (list_.empty())
|
if (list_.empty())
|
||||||
|
|
|
||||||
|
|
@ -108,7 +108,8 @@ class PAssign_ : public Statement {
|
||||||
NetAssign_* elaborate_lval(Design*, NetScope*scope) const;
|
NetAssign_* elaborate_lval(Design*, NetScope*scope) const;
|
||||||
NetExpr* elaborate_rval_(Design*, NetScope*, ivl_type_t lv_net_type,
|
NetExpr* elaborate_rval_(Design*, NetScope*, ivl_type_t lv_net_type,
|
||||||
ivl_variable_type_t lv_type,
|
ivl_variable_type_t lv_type,
|
||||||
unsigned lv_width) const;
|
unsigned lv_width,
|
||||||
|
bool force_unsigned =false) const;
|
||||||
NetExpr* elaborate_rval_(Design*, NetScope*, ivl_type_t ntype) const;
|
NetExpr* elaborate_rval_(Design*, NetScope*, ivl_type_t ntype) const;
|
||||||
|
|
||||||
NetExpr* elaborate_rval_obj_(Design*, NetScope*,
|
NetExpr* elaborate_rval_obj_(Design*, NetScope*,
|
||||||
|
|
@ -182,6 +183,8 @@ class PBlock : public PScope, public Statement {
|
||||||
|
|
||||||
BL_TYPE bl_type() const { return bl_type_; }
|
BL_TYPE bl_type() const { return bl_type_; }
|
||||||
|
|
||||||
|
bool var_init_needs_explicit_lifetime() const;
|
||||||
|
|
||||||
// This is only used if this block is the statement list for a
|
// This is only used if this block is the statement list for a
|
||||||
// constructor. We look for a PChainConstructor as the first
|
// constructor. We look for a PChainConstructor as the first
|
||||||
// statement, and if it is there, extract it.
|
// statement, and if it is there, extract it.
|
||||||
|
|
|
||||||
30
compiler.h
30
compiler.h
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef IVL_compiler_H
|
#ifndef IVL_compiler_H
|
||||||
#define IVL_compiler_H
|
#define IVL_compiler_H
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1999-2014 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 1999-2016 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -142,7 +142,8 @@ extern int build_library_index(const char*path, bool key_case_sensitive);
|
||||||
|
|
||||||
/* This is the generation of Verilog that the compiler is asked to
|
/* This is the generation of Verilog that the compiler is asked to
|
||||||
support. Then there are also more detailed controls for more
|
support. Then there are also more detailed controls for more
|
||||||
specific language features. */
|
specific language features. Note that the compiler often assumes
|
||||||
|
this is an ordered list. */
|
||||||
enum generation_t {
|
enum generation_t {
|
||||||
GN_VER1995 = 1,
|
GN_VER1995 = 1,
|
||||||
GN_VER2001_NOCONFIG = 2,
|
GN_VER2001_NOCONFIG = 2,
|
||||||
|
|
@ -186,25 +187,24 @@ extern bool gn_strict_ca_eval_flag;
|
||||||
standard expression width rules. */
|
standard expression width rules. */
|
||||||
extern bool gn_strict_expr_width_flag;
|
extern bool gn_strict_expr_width_flag;
|
||||||
|
|
||||||
/* If variables can be converted to uwires by a continuous assignment
|
/* If this flag is true, then don't add a for-loop control variable
|
||||||
(assuming no procedural assign, then return true. This will be true
|
to an implicit event_expression list if it is only used inside the
|
||||||
for SystemVerilog */
|
loop. */
|
||||||
static inline bool gn_var_can_be_uwire(void)
|
extern bool gn_shared_loop_index_flag;
|
||||||
|
|
||||||
|
static inline bool gn_system_verilog(void)
|
||||||
{
|
{
|
||||||
if (generation_flag == GN_VER2005_SV ||
|
if (generation_flag >= GN_VER2005_SV)
|
||||||
generation_flag == GN_VER2009 ||
|
|
||||||
generation_flag == GN_VER2012)
|
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool gn_system_verilog(void)
|
/* If variables can be converted to uwires by a continuous assignment
|
||||||
|
(assuming no procedural assign), then return true. This will be true
|
||||||
|
for SystemVerilog */
|
||||||
|
static inline bool gn_var_can_be_uwire(void)
|
||||||
{
|
{
|
||||||
if (generation_flag == GN_VER2005_SV ||
|
return gn_system_verilog();
|
||||||
generation_flag == GN_VER2009 ||
|
|
||||||
generation_flag == GN_VER2012)
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool gn_modules_nest(void)
|
static inline bool gn_modules_nest(void)
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
%{
|
%{
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2014 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2001-2016 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -124,7 +124,8 @@ int cmdfile_stack_ptr = 0;
|
||||||
"-c" { return TOK_Dc; }
|
"-c" { return TOK_Dc; }
|
||||||
"-f" { return TOK_Dc; }
|
"-f" { return TOK_Dc; }
|
||||||
|
|
||||||
/* Notice the -v flag. */
|
/* Notice the -l or -v flag. */
|
||||||
|
"-l" { return TOK_Dv; }
|
||||||
"-v" { return TOK_Dv; }
|
"-v" { return TOK_Dv; }
|
||||||
|
|
||||||
/* Notice the -y flag. */
|
/* Notice the -y flag. */
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,15 @@
|
||||||
.TH iverilog 1 "Aug 7th, 2015" "" "Version %M.%n%E"
|
.TH iverilog 1 "Oct 2nd, 2016" "" "Version %M.%n%E"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
iverilog - Icarus Verilog compiler
|
iverilog - Icarus Verilog compiler
|
||||||
|
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.B iverilog
|
.B iverilog
|
||||||
[\-ESVv] [\-Bpath] [\-ccmdfile|\-fcmdfile] [\-Dmacro[=defn]]
|
[\-ESVv] [\-Bpath] [\-ccmdfile|\-fcmdfile] [\-Dmacro[=defn]]
|
||||||
[\-Pparameter=value] [\-pflag=value]
|
[\-Pparameter=value] [\-pflag=value] [\-dname]
|
||||||
[\-dname] [\-g1995|\-g2001|\-g2005|\-g2005-sv|\-g2009|\-g2012|\-g<feature>]
|
[\-g1995\:|\-g2001\:|\-g2005\:|\-g2005-sv\:|\-g2009\:|\-g2012\:|\-g<feature>]
|
||||||
[\-Iincludedir] [\-mmodule] [\-M[mode=]file] [\-Nfile] [\-ooutputfilename]
|
[\-Iincludedir] [\-mmodule] [\-M[mode=]file] [\-Nfile] [\-ooutputfilename]
|
||||||
[\-stopmodule] [\-ttype] [\-Tmin/typ/max] [\-Wclass] [\-ypath] sourcefile
|
[\-stopmodule] [\-ttype] [\-Tmin/typ/max] [\-Wclass] [\-ypath] [\-lfile]
|
||||||
|
sourcefile
|
||||||
|
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
.PP
|
.PP
|
||||||
|
|
@ -133,12 +134,29 @@ parameter assignment is evaluated as a lossless expression, as is any
|
||||||
expression containing an unsized constant number, and unsized constant
|
expression containing an unsized constant number, and unsized constant
|
||||||
numbers are not truncated to integer width.
|
numbers are not truncated to integer width.
|
||||||
.TP 8
|
.TP 8
|
||||||
|
.B -gshared-loop-index\fI|\fP-gno-shared-loop-index
|
||||||
|
Enable or disable (default) the exclusion of for-loop control variables
|
||||||
|
from implicit event_expression lists. When enabled, if a for-loop control
|
||||||
|
variable (loop index) is only used inside the for-loop statement, the
|
||||||
|
compiler will not include it in an implicit event_expression list it
|
||||||
|
calculates for that statement or any enclosing statement. This allows
|
||||||
|
the same control variable to be used in multiple processes without risk
|
||||||
|
of entering an infinite loop caused by each process triggering all other
|
||||||
|
processes that use the same varaible. For strict compliance with the
|
||||||
|
standards, this behaviour should be disabled.
|
||||||
|
.TP 8
|
||||||
.B -I\fIincludedir\fP
|
.B -I\fIincludedir\fP
|
||||||
Append directory \fIincludedir\fP to list of directories searched
|
Append directory \fIincludedir\fP to list of directories searched
|
||||||
for Verilog include files. The \fB\-I\fP switch may be used many times
|
for Verilog include files. The \fB\-I\fP switch may be used many times
|
||||||
to specify several directories to search, the directories are searched
|
to specify several directories to search, the directories are searched
|
||||||
in the order they appear on the command line.
|
in the order they appear on the command line.
|
||||||
.TP 8
|
.TP 8
|
||||||
|
.B -l\fIfile\fP
|
||||||
|
Add the specified file to the list of source files to be compiled,
|
||||||
|
but mark it as a library file. All modules contained within that
|
||||||
|
file will be treated as library modules, and only elaborated if
|
||||||
|
they are instantiated by other modules in the design.
|
||||||
|
.TP 8
|
||||||
.B -M\fIpath\fP
|
.B -M\fIpath\fP
|
||||||
This is equivalent to \fB\-Mall=path\fP. Preserved for backwards
|
This is equivalent to \fB\-Mall=path\fP. Preserved for backwards
|
||||||
compatibility.
|
compatibility.
|
||||||
|
|
@ -402,6 +420,15 @@ A \fB\-c\fP or \fB\-f\fP token prefixes a command file, exactly like it
|
||||||
does on the command line. The cmdfile may be on the same line or the
|
does on the command line. The cmdfile may be on the same line or the
|
||||||
next non-comment line.
|
next non-comment line.
|
||||||
|
|
||||||
|
.TP 8
|
||||||
|
.B -l\ \fIfile\fP -v\ \fIfile\fP
|
||||||
|
A \fB\-l\fP token prefixes a library file in the command file,
|
||||||
|
exactly like it does on the command line. The parameter to the \fB\-l\fP
|
||||||
|
flag may be on the same line or the next non-comment line. \fB\-v\fP is
|
||||||
|
an alias for \fB\-l\fP, provided for compatibility with other simulators.
|
||||||
|
|
||||||
|
Variables in the \fIfile\fP are substituted.
|
||||||
|
|
||||||
.TP 8
|
.TP 8
|
||||||
.B -y\ \fIlibdir\fP
|
.B -y\ \fIlibdir\fP
|
||||||
A \fB\-y\fP token prefixes a library directory in the command file,
|
A \fB\-y\fP token prefixes a library directory in the command file,
|
||||||
|
|
@ -532,7 +559,7 @@ Tips on using, debugging, and developing the compiler can be found at
|
||||||
|
|
||||||
.SH COPYRIGHT
|
.SH COPYRIGHT
|
||||||
.nf
|
.nf
|
||||||
Copyright \(co 2002\-2015 Stephen Williams
|
Copyright \(co 2002\-2016 Stephen Williams
|
||||||
|
|
||||||
This document can be freely redistributed according to the terms of the
|
This document can be freely redistributed according to the terms of the
|
||||||
GNU General Public License version 2.0
|
GNU General Public License version 2.0
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000-2015 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2000-2016 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -44,7 +44,7 @@ const char HELP[] =
|
||||||
" [-M [mode=]depfile] [-m module]\n"
|
" [-M [mode=]depfile] [-m module]\n"
|
||||||
" [-N file] [-o filename] [-p flag=value]\n"
|
" [-N file] [-o filename] [-p flag=value]\n"
|
||||||
" [-s topmodule] [-t target] [-T min|typ|max]\n"
|
" [-s topmodule] [-t target] [-T min|typ|max]\n"
|
||||||
" [-W class] [-y dir] [-Y suf] source_file(s)\n"
|
" [-W class] [-y dir] [-Y suf] [-l file] source_file(s)\n"
|
||||||
"\n"
|
"\n"
|
||||||
"See the man page for details.";
|
"See the man page for details.";
|
||||||
|
|
||||||
|
|
@ -128,6 +128,7 @@ const char*gen_icarus = "icarus-misc";
|
||||||
const char*gen_io_range_error = "io-range-error";
|
const char*gen_io_range_error = "io-range-error";
|
||||||
const char*gen_strict_ca_eval = "no-strict-ca-eval";
|
const char*gen_strict_ca_eval = "no-strict-ca-eval";
|
||||||
const char*gen_strict_expr_width = "no-strict-expr-width";
|
const char*gen_strict_expr_width = "no-strict-expr-width";
|
||||||
|
const char*gen_shared_loop_index = "no-shared-loop-index";
|
||||||
const char*gen_verilog_ams = "no-verilog-ams";
|
const char*gen_verilog_ams = "no-verilog-ams";
|
||||||
|
|
||||||
/* Boolean: true means use a default include dir, false means don't */
|
/* Boolean: true means use a default include dir, false means don't */
|
||||||
|
|
@ -730,6 +731,12 @@ static int process_generation(const char*name)
|
||||||
else if (strcmp(name,"no-strict-expr-width") == 0)
|
else if (strcmp(name,"no-strict-expr-width") == 0)
|
||||||
gen_strict_expr_width = "no-strict-expr-width";
|
gen_strict_expr_width = "no-strict-expr-width";
|
||||||
|
|
||||||
|
else if (strcmp(name,"shared-loop-index") == 0)
|
||||||
|
gen_shared_loop_index = "shared-loop-index";
|
||||||
|
|
||||||
|
else if (strcmp(name,"no-shared-loop-index") == 0)
|
||||||
|
gen_shared_loop_index = "no-shared-loop-index";
|
||||||
|
|
||||||
else if (strcmp(name,"verilog-ams") == 0)
|
else if (strcmp(name,"verilog-ams") == 0)
|
||||||
gen_verilog_ams = "verilog-ams";
|
gen_verilog_ams = "verilog-ams";
|
||||||
|
|
||||||
|
|
@ -755,7 +762,8 @@ static int process_generation(const char*name)
|
||||||
" icarus-misc | no-icarus-misc\n"
|
" icarus-misc | no-icarus-misc\n"
|
||||||
" io-range-error | no-io-range-error\n"
|
" io-range-error | no-io-range-error\n"
|
||||||
" strict-ca-eval | no-strict-ca-eval\n"
|
" strict-ca-eval | no-strict-ca-eval\n"
|
||||||
" strict-expr-width | no-strict-expr-width\n");
|
" strict-expr-width | no-strict-expr-width\n"
|
||||||
|
" shared-loop-index | no-shared-loop-index\n");
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
@ -920,7 +928,7 @@ int main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((opt = getopt(argc, argv, "B:c:D:d:Ef:g:hI:M:m:N:o:P:p:Ss:T:t:vVW:y:Y:")) != EOF) {
|
while ((opt = getopt(argc, argv, "B:c:D:d:Ef:g:hl:I:M:m:N:o:P:p:Ss:T:t:vVW:y:Y:")) != EOF) {
|
||||||
|
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'B':
|
case 'B':
|
||||||
|
|
@ -975,6 +983,10 @@ int main(int argc, char **argv)
|
||||||
process_include_dir(optarg);
|
process_include_dir(optarg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'l':
|
||||||
|
process_file_name(optarg, 1);
|
||||||
|
break;
|
||||||
|
|
||||||
case 'M':
|
case 'M':
|
||||||
if (process_depfile(optarg) != 0)
|
if (process_depfile(optarg) != 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
@ -1108,6 +1120,7 @@ int main(int argc, char **argv)
|
||||||
fprintf(iconfig_file, "generation:%s\n", gen_io_range_error);
|
fprintf(iconfig_file, "generation:%s\n", gen_io_range_error);
|
||||||
fprintf(iconfig_file, "generation:%s\n", gen_strict_ca_eval);
|
fprintf(iconfig_file, "generation:%s\n", gen_strict_ca_eval);
|
||||||
fprintf(iconfig_file, "generation:%s\n", gen_strict_expr_width);
|
fprintf(iconfig_file, "generation:%s\n", gen_strict_expr_width);
|
||||||
|
fprintf(iconfig_file, "generation:%s\n", gen_shared_loop_index);
|
||||||
fprintf(iconfig_file, "generation:%s\n", gen_verilog_ams);
|
fprintf(iconfig_file, "generation:%s\n", gen_verilog_ams);
|
||||||
fprintf(iconfig_file, "generation:%s\n", gen_icarus);
|
fprintf(iconfig_file, "generation:%s\n", gen_icarus);
|
||||||
fprintf(iconfig_file, "warnings:%s\n", warning_flags);
|
fprintf(iconfig_file, "warnings:%s\n", warning_flags);
|
||||||
|
|
|
||||||
121
elab_expr.cc
121
elab_expr.cc
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1999-2015 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 1999-2016 Stephen Williams (steve@icarus.com)
|
||||||
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
|
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
|
|
@ -90,7 +90,7 @@ static NetBranch* find_existing_implicit_branch(NetNet*sig, NetNet*gnd)
|
||||||
|
|
||||||
NetExpr* elaborate_rval_expr(Design*des, NetScope*scope, ivl_type_t lv_net_type,
|
NetExpr* elaborate_rval_expr(Design*des, NetScope*scope, ivl_type_t lv_net_type,
|
||||||
ivl_variable_type_t lv_type, unsigned lv_width,
|
ivl_variable_type_t lv_type, unsigned lv_width,
|
||||||
PExpr*expr, bool need_const)
|
PExpr*expr, bool need_const, bool force_unsigned)
|
||||||
{
|
{
|
||||||
if (debug_elaborate) {
|
if (debug_elaborate) {
|
||||||
cerr << expr->get_fileline() << ": elaborate_rval_expr: "
|
cerr << expr->get_fileline() << ": elaborate_rval_expr: "
|
||||||
|
|
@ -135,7 +135,7 @@ NetExpr* elaborate_rval_expr(Design*des, NetScope*scope, ivl_type_t lv_net_type,
|
||||||
}
|
}
|
||||||
|
|
||||||
return elab_and_eval(des, scope, expr, context_wid, need_const,
|
return elab_and_eval(des, scope, expr, context_wid, need_const,
|
||||||
false, lv_type);
|
false, lv_type, force_unsigned);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -675,10 +675,7 @@ NetExpr* PEBComp::elaborate_expr(Design*des, NetScope*scope,
|
||||||
NetExpr*tmp = new NetEBComp(op_, lp, rp);
|
NetExpr*tmp = new NetEBComp(op_, lp, rp);
|
||||||
tmp->set_line(*this);
|
tmp->set_line(*this);
|
||||||
|
|
||||||
tmp = pad_to_width(tmp, expr_wid, *this);
|
return pad_to_width(tmp, expr_wid, signed_flag_, *this);
|
||||||
tmp->cast_signed(signed_flag_);
|
|
||||||
|
|
||||||
return tmp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned PEBLogic::test_width(Design*, NetScope*, width_mode_t&)
|
unsigned PEBLogic::test_width(Design*, NetScope*, width_mode_t&)
|
||||||
|
|
@ -716,10 +713,7 @@ NetExpr*PEBLogic::elaborate_expr(Design*des, NetScope*scope,
|
||||||
NetExpr*tmp = new NetEBLogic(op_, lp, rp);
|
NetExpr*tmp = new NetEBLogic(op_, lp, rp);
|
||||||
tmp->set_line(*this);
|
tmp->set_line(*this);
|
||||||
|
|
||||||
tmp = pad_to_width(tmp, expr_wid, *this);
|
return pad_to_width(tmp, expr_wid, signed_flag_, *this);
|
||||||
tmp->cast_signed(signed_flag_);
|
|
||||||
|
|
||||||
return tmp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned PEBLeftWidth::test_width(Design*des, NetScope*scope, width_mode_t&mode)
|
unsigned PEBLeftWidth::test_width(Design*des, NetScope*scope, width_mode_t&mode)
|
||||||
|
|
@ -1035,8 +1029,7 @@ NetExpr*PEBShift::elaborate_expr_leaf(Design*des, NetExpr*lp, NetExpr*rp,
|
||||||
tmp->set_line(*this);
|
tmp->set_line(*this);
|
||||||
tmp = new NetESelect(lp, tmp, 1);
|
tmp = new NetESelect(lp, tmp, 1);
|
||||||
tmp->set_line(*this);
|
tmp->set_line(*this);
|
||||||
tmp = pad_to_width(tmp, expr_wid, *this);
|
tmp = pad_to_width(tmp, expr_wid, true, *this);
|
||||||
tmp->cast_signed(true);
|
|
||||||
|
|
||||||
delete rp;
|
delete rp;
|
||||||
return tmp;
|
return tmp;
|
||||||
|
|
@ -1414,23 +1407,7 @@ NetExpr*PECallFunction::cast_to_width_(NetExpr*expr, unsigned wid) const
|
||||||
<< " from expr_width()=" << expr->expr_width() << endl;
|
<< " from expr_width()=" << expr->expr_width() << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the expression is a const, then replace it with a new
|
return cast_to_width(expr, wid, signed_flag_, *this);
|
||||||
const. This is a more efficient result. */
|
|
||||||
if (NetEConst*tmp = dynamic_cast<NetEConst*>(expr)) {
|
|
||||||
tmp->cast_signed(signed_flag_);
|
|
||||||
if (wid != tmp->expr_width()) {
|
|
||||||
tmp = new NetEConst(verinum(tmp->value(), wid));
|
|
||||||
tmp->set_line(*this);
|
|
||||||
delete expr;
|
|
||||||
}
|
|
||||||
return tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
NetESelect*tmp = new NetESelect(expr, 0, wid);
|
|
||||||
tmp->cast_signed(signed_flag_);
|
|
||||||
tmp->set_line(*this);
|
|
||||||
|
|
||||||
return tmp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -1606,10 +1583,7 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope,
|
||||||
if (missing_parms || parm_errors)
|
if (missing_parms || parm_errors)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
NetExpr*tmp = pad_to_width(fun, expr_wid, *this);
|
return pad_to_width(fun, expr_wid, signed_flag_, *this);
|
||||||
tmp->cast_signed(signed_flag_);
|
|
||||||
|
|
||||||
return tmp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NetExpr* PECallFunction::elaborate_access_func_(Design*des, NetScope*scope,
|
NetExpr* PECallFunction::elaborate_access_func_(Design*des, NetScope*scope,
|
||||||
|
|
@ -1666,10 +1640,7 @@ NetExpr* PECallFunction::elaborate_access_func_(Design*des, NetScope*scope,
|
||||||
NetExpr*tmp = new NetEAccess(branch, nature);
|
NetExpr*tmp = new NetEAccess(branch, nature);
|
||||||
tmp->set_line(*this);
|
tmp->set_line(*this);
|
||||||
|
|
||||||
tmp = pad_to_width(tmp, expr_wid, *this);
|
return pad_to_width(tmp, expr_wid, signed_flag_, *this);
|
||||||
tmp->cast_signed(signed_flag_);
|
|
||||||
|
|
||||||
return tmp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -2281,10 +2252,7 @@ NetExpr* PECallFunction::elaborate_base_(Design*des, NetScope*scope, NetScope*ds
|
||||||
if(res->darray_type())
|
if(res->darray_type())
|
||||||
return func;
|
return func;
|
||||||
|
|
||||||
NetExpr*tmp = pad_to_width(func, expr_wid, *this);
|
return pad_to_width(func, expr_wid, signed_flag_, *this);
|
||||||
tmp->cast_signed(signed_flag_);
|
|
||||||
|
|
||||||
return tmp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cerr << get_fileline() << ": internal error: Unable to locate "
|
cerr << get_fileline() << ": internal error: Unable to locate "
|
||||||
|
|
@ -2521,22 +2489,54 @@ NetExpr* PECallFunction::elaborate_expr_method_(Design*des, NetScope*scope,
|
||||||
|
|
||||||
unsigned PECastSize::test_width(Design*des, NetScope*scope, width_mode_t&)
|
unsigned PECastSize::test_width(Design*des, NetScope*scope, width_mode_t&)
|
||||||
{
|
{
|
||||||
expr_width_ = size_;
|
ivl_assert(*this, size_);
|
||||||
|
ivl_assert(*this, base_);
|
||||||
|
|
||||||
|
NetExpr*size_ex = elab_and_eval(des, scope, size_, -1, true);
|
||||||
|
NetEConst*size_ce = dynamic_cast<NetEConst*>(size_ex);
|
||||||
|
expr_width_ = size_ce ? size_ce->value().as_ulong() : 0;
|
||||||
|
delete size_ex;
|
||||||
|
if (expr_width_ == 0) {
|
||||||
|
cerr << get_fileline() << ": error: Cast size expression "
|
||||||
|
"must be constant and greater than zero." << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
width_mode_t tmp_mode = PExpr::SIZED;
|
width_mode_t tmp_mode = PExpr::SIZED;
|
||||||
base_->test_width(des, scope, tmp_mode);
|
base_->test_width(des, scope, tmp_mode);
|
||||||
|
|
||||||
return size_;
|
if (!type_is_vectorable(base_->expr_type())) {
|
||||||
|
cerr << get_fileline() << ": error: Cast base expression "
|
||||||
|
"must be a vector type." << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
expr_type_ = base_->expr_type();
|
||||||
|
min_width_ = expr_width_;
|
||||||
|
signed_flag_ = base_->has_sign();
|
||||||
|
|
||||||
|
return expr_width_;
|
||||||
}
|
}
|
||||||
|
|
||||||
NetExpr* PECastSize::elaborate_expr(Design*des, NetScope*scope,
|
NetExpr* PECastSize::elaborate_expr(Design*des, NetScope*scope,
|
||||||
unsigned, unsigned) const
|
unsigned expr_wid, unsigned flags) const
|
||||||
{
|
{
|
||||||
NetExpr*sub = base_->elaborate_expr(des, scope, base_->expr_width(), NO_FLAGS);
|
flags &= ~SYS_TASK_ARG; // don't propagate the SYS_TASK_ARG flag
|
||||||
NetESelect*sel = new NetESelect(sub, 0, size_);
|
|
||||||
sel->set_line(*this);
|
|
||||||
|
|
||||||
return sel;
|
ivl_assert(*this, size_);
|
||||||
|
ivl_assert(*this, base_);
|
||||||
|
|
||||||
|
NetExpr*sub = base_->elaborate_expr(des, scope, base_->expr_width(), flags);
|
||||||
|
|
||||||
|
// Perform the cast. The extension method (zero/sign), if needed,
|
||||||
|
// depends on the type of the base expression.
|
||||||
|
NetExpr*tmp = cast_to_width(sub, expr_width_, base_->has_sign(), *this);
|
||||||
|
|
||||||
|
// Pad up to the expression width. The extension method (zero/sign)
|
||||||
|
// depends on the type of enclosing expression.
|
||||||
|
return pad_to_width(tmp, expr_wid, signed_flag_, *this);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned PECastType::test_width(Design*des, NetScope*scope, width_mode_t&wid)
|
unsigned PECastType::test_width(Design*des, NetScope*scope, width_mode_t&wid)
|
||||||
|
|
@ -2851,8 +2851,7 @@ NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
NetExpr*tmp = pad_to_width(concat, expr_wid, *this);
|
NetExpr*tmp = pad_to_width(concat, expr_wid, signed_flag_, *this);
|
||||||
tmp->cast_signed(signed_flag_);
|
|
||||||
|
|
||||||
concat_depth -= 1;
|
concat_depth -= 1;
|
||||||
return tmp;
|
return tmp;
|
||||||
|
|
@ -3769,10 +3768,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
||||||
|
|
||||||
if (!tmp) return 0;
|
if (!tmp) return 0;
|
||||||
|
|
||||||
tmp = pad_to_width(tmp, expr_wid, *this);
|
return pad_to_width(tmp, expr_wid, signed_flag_, *this);
|
||||||
tmp->cast_signed(signed_flag_);
|
|
||||||
|
|
||||||
return tmp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the identifier names a signal (a register or wire)
|
// If the identifier names a signal (a register or wire)
|
||||||
|
|
@ -3808,10 +3804,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
||||||
<< ", tmp=" << *tmp << endl;
|
<< ", tmp=" << *tmp << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
tmp = pad_to_width(tmp, expr_wid, *this);
|
return pad_to_width(tmp, expr_wid, signed_flag_, *this);
|
||||||
tmp->cast_signed(signed_flag_);
|
|
||||||
|
|
||||||
return tmp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the identifier is a named event
|
// If the identifier is a named event
|
||||||
|
|
@ -3911,9 +3904,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
||||||
member_comp);
|
member_comp);
|
||||||
if (!tmp) return 0;
|
if (!tmp) return 0;
|
||||||
|
|
||||||
tmp = pad_to_width(tmp, expr_wid, *this);
|
return pad_to_width(tmp, expr_wid, signed_flag_, *this);
|
||||||
tmp->cast_signed(signed_flag_);
|
|
||||||
return tmp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (net->class_type() != 0) {
|
if (net->class_type() != 0) {
|
||||||
|
|
@ -4492,7 +4483,7 @@ NetExpr* PEIdent::elaborate_expr_param_(Design*des,
|
||||||
<< "Elaborate parameter <" << path_
|
<< "Elaborate parameter <" << path_
|
||||||
<< "> as enumeration constant." << *etmp << endl;
|
<< "> as enumeration constant." << *etmp << endl;
|
||||||
tmp = etmp->dup_expr();
|
tmp = etmp->dup_expr();
|
||||||
tmp = pad_to_width(tmp, expr_wid, *this);
|
tmp = pad_to_width(tmp, expr_wid, signed_flag_, *this);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
perm_string name = peek_tail_name(path_);
|
perm_string name = peek_tail_name(path_);
|
||||||
|
|
@ -6082,7 +6073,7 @@ NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope,
|
||||||
}
|
}
|
||||||
tmp->set_line(*this);
|
tmp->set_line(*this);
|
||||||
}
|
}
|
||||||
tmp = pad_to_width(tmp, expr_wid, *this);
|
tmp = pad_to_width(tmp, expr_wid, signed_flag_, *this);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '&': // Reduction AND
|
case '&': // Reduction AND
|
||||||
|
|
@ -6100,7 +6091,7 @@ NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope,
|
||||||
}
|
}
|
||||||
tmp = new NetEUReduce(op_, ip);
|
tmp = new NetEUReduce(op_, ip);
|
||||||
tmp->set_line(*this);
|
tmp->set_line(*this);
|
||||||
tmp = pad_to_width(tmp, expr_wid, *this);
|
tmp = pad_to_width(tmp, expr_wid, signed_flag_, *this);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '~':
|
case '~':
|
||||||
|
|
|
||||||
39
elab_lval.cc
39
elab_lval.cc
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2000-2016 Stephen Williams (steve@icarus.com)
|
||||||
* Copyright CERN 2012-2013 / Stephen Williams (steve@icarus.com)
|
* Copyright CERN 2012-2013 / Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
|
|
@ -138,6 +138,9 @@ NetAssign_* PEConcat::elaborate_lval(Design*des,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* A concatenation is always unsigned. */
|
||||||
|
tmp->set_signed(false);
|
||||||
|
|
||||||
/* Link the new l-value to the previous one. */
|
/* Link the new l-value to the previous one. */
|
||||||
NetAssign_*last = tmp;
|
NetAssign_*last = tmp;
|
||||||
while (last->more)
|
while (last->more)
|
||||||
|
|
@ -287,13 +290,13 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
||||||
}
|
}
|
||||||
|
|
||||||
// We are processing the tail of a string of names. For
|
// We are processing the tail of a string of names. For
|
||||||
// example, the verilog may be "a.b.c", so we are processing
|
// example, the Verilog may be "a.b.c", so we are processing
|
||||||
// "c" at this point. (Note that if method_name is not nil,
|
// "c" at this point. (Note that if method_name is not nil,
|
||||||
// then this is "a.b.c.method" and "a.b.c" is a struct or class.)
|
// then this is "a.b.c.method" and "a.b.c" is a struct or class.)
|
||||||
const name_component_t&name_tail = path_.back();
|
const name_component_t&name_tail = path_.back();
|
||||||
|
|
||||||
// Use the last index to determine what kind of select
|
// Use the last index to determine what kind of select
|
||||||
// (bit/part/etc) we are processing. For example, the verilog
|
// (bit/part/etc) we are processing. For example, the Verilog
|
||||||
// may be "a.b.c[1][2][<index>]". All but the last index must
|
// may be "a.b.c[1][2][<index>]". All but the last index must
|
||||||
// be simple expressions, only the <index> may be a part
|
// be simple expressions, only the <index> may be a part
|
||||||
// select etc., so look at it to determine how we will be
|
// select etc., so look at it to determine how we will be
|
||||||
|
|
@ -399,6 +402,7 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
||||||
/* No select expressions. */
|
/* No select expressions. */
|
||||||
|
|
||||||
NetAssign_*lv = new NetAssign_(reg);
|
NetAssign_*lv = new NetAssign_(reg);
|
||||||
|
lv->set_signed(reg->get_signed());
|
||||||
|
|
||||||
return lv;
|
return lv;
|
||||||
}
|
}
|
||||||
|
|
@ -687,20 +691,24 @@ bool PEIdent::elaborate_lval_net_bit_(Design*des,
|
||||||
unsigned long lwid;
|
unsigned long lwid;
|
||||||
bool rcl = reg->sb_to_slice(prefix_indices, lsb, loff, lwid);
|
bool rcl = reg->sb_to_slice(prefix_indices, lsb, loff, lwid);
|
||||||
ivl_assert(*this, rcl);
|
ivl_assert(*this, rcl);
|
||||||
cerr << get_fileline() << ": warning: L-value packed array "
|
if (warn_ob_select) {
|
||||||
<< "select of " << reg->name();
|
cerr << get_fileline()
|
||||||
|
<< ": warning: L-value packed array select of "
|
||||||
|
<< reg->name();
|
||||||
if (reg->unpacked_dimensions() > 0) cerr << "[]";
|
if (reg->unpacked_dimensions() > 0) cerr << "[]";
|
||||||
cerr << " has an undefined index." << endl;
|
cerr << " has an undefined index." << endl;
|
||||||
|
}
|
||||||
lv->set_part(new NetEConst(verinum(verinum::Vx)), lwid);
|
lv->set_part(new NetEConst(verinum(verinum::Vx)), lwid);
|
||||||
return true;
|
return true;
|
||||||
// The index is undefined and this is a bit select.
|
// The index is undefined and this is a bit select.
|
||||||
} else {
|
} else {
|
||||||
cerr << get_fileline() << ": warning: L-value bit select of "
|
if (warn_ob_select) {
|
||||||
|
cerr << get_fileline()
|
||||||
|
<< ": warning: L-value bit select of "
|
||||||
<< reg->name();
|
<< reg->name();
|
||||||
if (reg->unpacked_dimensions() > 0) cerr << "[]";
|
if (reg->unpacked_dimensions() > 0) cerr << "[]";
|
||||||
cerr << " has an undefined index." << endl;
|
cerr << " has an undefined index." << endl;
|
||||||
|
}
|
||||||
lv->set_part(new NetEConst(verinum(verinum::Vx)), 1);
|
lv->set_part(new NetEConst(verinum(verinum::Vx)), 1);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -797,12 +805,10 @@ bool PEIdent::elaborate_lval_net_bit_(Design*des,
|
||||||
// Constant bit select that does something useful.
|
// Constant bit select that does something useful.
|
||||||
long loff = reg->sb_to_idx(prefix_indices,lsb);
|
long loff = reg->sb_to_idx(prefix_indices,lsb);
|
||||||
|
|
||||||
if (loff < 0 || loff >= (long)reg->vector_width()) {
|
if (warn_ob_select && (loff < 0 || loff >= (long)reg->vector_width())) {
|
||||||
cerr << get_fileline() << ": error: bit select "
|
cerr << get_fileline() << ": warning: bit select "
|
||||||
<< reg->name() << "[" <<lsb<<"]"
|
<< reg->name() << "[" <<lsb<<"]"
|
||||||
<< " is out of range." << endl;
|
<< " is out of range." << endl;
|
||||||
des->errors += 1;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reg->type()==NetNet::UNRESOLVED_WIRE) {
|
if (reg->type()==NetNet::UNRESOLVED_WIRE) {
|
||||||
|
|
@ -868,10 +874,13 @@ bool PEIdent::elaborate_lval_net_part_(Design*des,
|
||||||
ivl_assert(*this, reg);
|
ivl_assert(*this, reg);
|
||||||
|
|
||||||
if (! parts_defined_flag) {
|
if (! parts_defined_flag) {
|
||||||
cerr << get_fileline() << ": warning: L-value part select of "
|
if (warn_ob_select) {
|
||||||
|
cerr << get_fileline()
|
||||||
|
<< ": warning: L-value part select of "
|
||||||
<< reg->name();
|
<< reg->name();
|
||||||
if (reg->unpacked_dimensions() > 0) cerr << "[]";
|
if (reg->unpacked_dimensions() > 0) cerr << "[]";
|
||||||
cerr << " has an undefined index." << endl;
|
cerr << " has an undefined index." << endl;
|
||||||
|
}
|
||||||
// Use a width of two here so we can distinguish between an
|
// Use a width of two here so we can distinguish between an
|
||||||
// undefined bit or part select.
|
// undefined bit or part select.
|
||||||
lv->set_part(new NetEConst(verinum(verinum::Vx)), 2);
|
lv->set_part(new NetEConst(verinum(verinum::Vx)), 2);
|
||||||
|
|
@ -934,11 +943,11 @@ bool PEIdent::elaborate_lval_net_part_(Design*des,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the part select extends beyond the extremes of the
|
/* If the part select extends beyond the extremes of the
|
||||||
variable, then report an error. Note that loff is
|
variable, then output a warning. Note that loff is
|
||||||
converted to normalized form so is relative the
|
converted to normalized form so is relative the
|
||||||
variable pins. */
|
variable pins. */
|
||||||
|
|
||||||
if (loff < 0 || moff >= (long)reg->vector_width()) {
|
if (warn_ob_select && (loff < 0 || moff >= (long)reg->vector_width())) {
|
||||||
cerr << get_fileline() << ": warning: Part select "
|
cerr << get_fileline() << ": warning: Part select "
|
||||||
<< reg->name() << "[" << msb<<":"<<lsb<<"]"
|
<< reg->name() << "[" << msb<<":"<<lsb<<"]"
|
||||||
<< " is out of range." << endl;
|
<< " is out of range." << endl;
|
||||||
|
|
|
||||||
27
elab_net.cc
27
elab_net.cc
|
|
@ -328,8 +328,34 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (prefix_indices.size()+1 < sig->packed_dims().size()) {
|
||||||
|
// Here we have a slice that doesn't have enough indices
|
||||||
|
// to get to a single slice. For example:
|
||||||
|
// wire [9:0][5:1] foo
|
||||||
|
// ... foo[4:3] ...
|
||||||
|
// Make this work by finding the indexed slices and
|
||||||
|
// creating a generated slice that spans the whole
|
||||||
|
// range.
|
||||||
|
long loff, moff;
|
||||||
|
unsigned long lwid, mwid;
|
||||||
|
bool lrc;
|
||||||
|
lrc = sig->sb_to_slice(prefix_indices, lsb, loff, lwid);
|
||||||
|
ivl_assert(*this, lrc);
|
||||||
|
lrc = sig->sb_to_slice(prefix_indices, msb, moff, mwid);
|
||||||
|
ivl_assert(*this, lrc);
|
||||||
|
ivl_assert(*this, lwid == mwid);
|
||||||
|
|
||||||
|
if (moff > loff) {
|
||||||
|
lidx = loff;
|
||||||
|
midx = moff + mwid - 1;
|
||||||
|
} else {
|
||||||
|
lidx = moff;
|
||||||
|
midx = loff + lwid - 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
long lidx_tmp = sig->sb_to_idx(prefix_indices, lsb);
|
long lidx_tmp = sig->sb_to_idx(prefix_indices, lsb);
|
||||||
long midx_tmp = sig->sb_to_idx(prefix_indices, msb);
|
long midx_tmp = sig->sb_to_idx(prefix_indices, msb);
|
||||||
|
|
||||||
/* Detect reversed indices of a part select. */
|
/* Detect reversed indices of a part select. */
|
||||||
if (lidx_tmp > midx_tmp) {
|
if (lidx_tmp > midx_tmp) {
|
||||||
cerr << get_fileline() << ": error: Part select "
|
cerr << get_fileline() << ": error: Part select "
|
||||||
|
|
@ -361,6 +387,7 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
|
||||||
|
|
||||||
midx = midx_tmp;
|
midx = midx_tmp;
|
||||||
lidx = lidx_tmp;
|
lidx = lidx_tmp;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000-2015 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2000-2016 Stephen Williams (steve@icarus.com)
|
||||||
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
|
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
|
|
@ -54,6 +54,15 @@
|
||||||
# include <cassert>
|
# include <cassert>
|
||||||
# include "ivl_assert.h"
|
# include "ivl_assert.h"
|
||||||
|
|
||||||
|
|
||||||
|
void set_scope_timescale(Design*des, NetScope*scope, PScope*pscope)
|
||||||
|
{
|
||||||
|
scope->time_unit(pscope->time_unit);
|
||||||
|
scope->time_precision(pscope->time_precision);
|
||||||
|
scope->time_from_timescale(pscope->time_from_timescale);
|
||||||
|
des->set_precision(pscope->time_precision);
|
||||||
|
}
|
||||||
|
|
||||||
typedef map<perm_string,LexicalScope::param_expr_t>::const_iterator mparm_it_t;
|
typedef map<perm_string,LexicalScope::param_expr_t>::const_iterator mparm_it_t;
|
||||||
|
|
||||||
static void collect_parm_item_(Design*des, NetScope*scope, perm_string name,
|
static void collect_parm_item_(Design*des, NetScope*scope, perm_string name,
|
||||||
|
|
@ -523,6 +532,7 @@ static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass)
|
||||||
class_scope->set_class_def(use_class);
|
class_scope->set_class_def(use_class);
|
||||||
use_class->set_class_scope(class_scope);
|
use_class->set_class_scope(class_scope);
|
||||||
use_class->set_definition_scope(scope);
|
use_class->set_definition_scope(scope);
|
||||||
|
set_scope_timescale(des, class_scope, pclass);
|
||||||
|
|
||||||
// Collect the properties, elaborate them, and add them to the
|
// Collect the properties, elaborate them, and add them to the
|
||||||
// elaborated class definition.
|
// elaborated class definition.
|
||||||
|
|
@ -654,8 +664,10 @@ static void elaborate_scope_task(Design*des, NetScope*scope, PTask*task)
|
||||||
task_scope->is_auto(task->is_auto());
|
task_scope->is_auto(task->is_auto());
|
||||||
task_scope->set_line(task);
|
task_scope->set_line(task);
|
||||||
|
|
||||||
if (scope==0)
|
if (scope==0) {
|
||||||
|
set_scope_timescale(des, task_scope, task);
|
||||||
des->add_root_task(task_scope, task);
|
des->add_root_task(task_scope, task);
|
||||||
|
}
|
||||||
|
|
||||||
if (debug_scopes) {
|
if (debug_scopes) {
|
||||||
cerr << task->get_fileline() << ": elaborate_scope_task: "
|
cerr << task->get_fileline() << ": elaborate_scope_task: "
|
||||||
|
|
@ -719,8 +731,10 @@ static void elaborate_scope_func(Design*des, NetScope*scope, PFunction*task)
|
||||||
task_scope->is_auto(task->is_auto());
|
task_scope->is_auto(task->is_auto());
|
||||||
task_scope->set_line(task);
|
task_scope->set_line(task);
|
||||||
|
|
||||||
if (scope==0)
|
if (scope==0) {
|
||||||
|
set_scope_timescale(des, task_scope, task);
|
||||||
des->add_root_task(task_scope, task);
|
des->add_root_task(task_scope, task);
|
||||||
|
}
|
||||||
|
|
||||||
if (debug_scopes) {
|
if (debug_scopes) {
|
||||||
cerr << task->get_fileline() << ": elaborate_scope_func: "
|
cerr << task->get_fileline() << ": elaborate_scope_func: "
|
||||||
|
|
@ -1750,11 +1764,7 @@ void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*s
|
||||||
|
|
||||||
instances[idx] = my_scope;
|
instances[idx] = my_scope;
|
||||||
|
|
||||||
// Set time units and precision.
|
set_scope_timescale(des, my_scope, mod);
|
||||||
my_scope->time_unit(mod->time_unit);
|
|
||||||
my_scope->time_precision(mod->time_precision);
|
|
||||||
my_scope->time_from_timescale(mod->time_from_timescale);
|
|
||||||
des->set_precision(mod->time_precision);
|
|
||||||
|
|
||||||
// Look for module parameter replacements. The "replace" map
|
// Look for module parameter replacements. The "replace" map
|
||||||
// maps parameter name to replacement expression that is
|
// maps parameter name to replacement expression that is
|
||||||
|
|
|
||||||
18
elab_sig.cc
18
elab_sig.cc
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000-2015 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2000-2016 Stephen Williams (steve@icarus.com)
|
||||||
* Copyright CERN 2012 / Stephen Williams (steve@icarus.com)
|
* Copyright CERN 2012 / Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
|
|
@ -1185,6 +1185,14 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||||
|
|
||||||
NetLogic*pull = 0;
|
NetLogic*pull = 0;
|
||||||
if (wtype == NetNet::SUPPLY0 || wtype == NetNet::SUPPLY1) {
|
if (wtype == NetNet::SUPPLY0 || wtype == NetNet::SUPPLY1) {
|
||||||
|
if (debug_elaborate) {
|
||||||
|
cerr << get_fileline() << ": debug: "
|
||||||
|
<< "Generate a SUPPLY pull for the ";
|
||||||
|
if (wtype == NetNet::SUPPLY0) cerr << "supply0";
|
||||||
|
else cerr << "supply1";
|
||||||
|
cerr << " net." << endl;
|
||||||
|
}
|
||||||
|
|
||||||
NetLogic::TYPE pull_type = (wtype==NetNet::SUPPLY1)
|
NetLogic::TYPE pull_type = (wtype==NetNet::SUPPLY1)
|
||||||
? NetLogic::PULLUP
|
? NetLogic::PULLUP
|
||||||
: NetLogic::PULLDOWN;
|
: NetLogic::PULLDOWN;
|
||||||
|
|
@ -1195,14 +1203,6 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||||
pull->pin(0).drive1(IVL_DR_SUPPLY);
|
pull->pin(0).drive1(IVL_DR_SUPPLY);
|
||||||
des->add_node(pull);
|
des->add_node(pull);
|
||||||
wtype = NetNet::WIRE;
|
wtype = NetNet::WIRE;
|
||||||
|
|
||||||
if (debug_elaborate) {
|
|
||||||
cerr << get_fileline() << ": debug: "
|
|
||||||
<< "Generate a SUPPLY pull for the ";
|
|
||||||
if (wtype == NetNet::SUPPLY0) cerr << "supply0";
|
|
||||||
else cerr << "supply1";
|
|
||||||
cerr << " net." << endl;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
14
elab_type.cc
14
elab_type.cc
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2012-2014 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2012-2016 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -17,11 +17,13 @@
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
# include "PExpr.h"
|
||||||
# include "pform_types.h"
|
# include "pform_types.h"
|
||||||
# include "netlist.h"
|
# include "netlist.h"
|
||||||
# include "netclass.h"
|
# include "netclass.h"
|
||||||
# include "netdarray.h"
|
# include "netdarray.h"
|
||||||
# include "netenum.h"
|
# include "netenum.h"
|
||||||
|
# include "netqueue.h"
|
||||||
# include "netparray.h"
|
# include "netparray.h"
|
||||||
# include "netscalar.h"
|
# include "netscalar.h"
|
||||||
# include "netstruct.h"
|
# include "netstruct.h"
|
||||||
|
|
@ -245,6 +247,16 @@ ivl_type_s* uarray_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Special case: if the dimension is null:nil. this is a queue.
|
||||||
|
if (cur->second==0 && dynamic_cast<PENull*>(cur->first)) {
|
||||||
|
cerr << get_fileline() << ": sorry: "
|
||||||
|
<< "SV queues inside classes are not yet supported." << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
|
||||||
|
ivl_type_s*res = new netqueue_t(btype);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
vector<netrange_t> dimensions;
|
vector<netrange_t> dimensions;
|
||||||
bool bad_range = evaluate_ranges(des, scope, dimensions, *dims);
|
bool bad_range = evaluate_ranges(des, scope, dimensions, *dims);
|
||||||
|
|
||||||
|
|
|
||||||
192
elaborate.cc
192
elaborate.cc
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1998-2015 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 1998-2016 Stephen Williams (steve@icarus.com)
|
||||||
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
|
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
|
|
@ -36,6 +36,7 @@
|
||||||
# include "PEvent.h"
|
# include "PEvent.h"
|
||||||
# include "PGenerate.h"
|
# include "PGenerate.h"
|
||||||
# include "PPackage.h"
|
# include "PPackage.h"
|
||||||
|
# include "PScope.h"
|
||||||
# include "PSpec.h"
|
# include "PSpec.h"
|
||||||
# include "netlist.h"
|
# include "netlist.h"
|
||||||
# include "netenum.h"
|
# include "netenum.h"
|
||||||
|
|
@ -50,6 +51,9 @@
|
||||||
# include "ivl_assert.h"
|
# include "ivl_assert.h"
|
||||||
|
|
||||||
|
|
||||||
|
// Implemented in elab_scope.cc
|
||||||
|
extern void set_scope_timescale(Design*des, NetScope*scope, PScope*pscope);
|
||||||
|
|
||||||
void PGate::elaborate(Design*, NetScope*) const
|
void PGate::elaborate(Design*, NetScope*) const
|
||||||
{
|
{
|
||||||
cerr << "internal error: what kind of gate? " <<
|
cerr << "internal error: what kind of gate? " <<
|
||||||
|
|
@ -787,7 +791,7 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
|
||||||
|
|
||||||
if (check_delay_count(des)) return;
|
if (check_delay_count(des)) return;
|
||||||
NetExpr* rise_time, *fall_time, *decay_time;
|
NetExpr* rise_time, *fall_time, *decay_time;
|
||||||
eval_delays(des, scope, rise_time, fall_time, decay_time);
|
eval_delays(des, scope, rise_time, fall_time, decay_time, true);
|
||||||
|
|
||||||
struct attrib_list_t*attrib_list;
|
struct attrib_list_t*attrib_list;
|
||||||
unsigned attrib_list_n = 0;
|
unsigned attrib_list_n = 0;
|
||||||
|
|
@ -1421,6 +1425,16 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
||||||
<< prts[0]->name() << " is coerced to inout." << endl;
|
<< prts[0]->name() << " is coerced to inout." << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!prts.empty() && (prts[0]->port_type() == NetNet::POUTPUT)
|
||||||
|
&& (prts[0]->type() != NetNet::REG)
|
||||||
|
&& prts[0]->pin(0).nexus()->has_floating_input()
|
||||||
|
&& pins[idx]->is_collapsible_net(des, scope)) {
|
||||||
|
prts[0]->port_type(NetNet::PINOUT);
|
||||||
|
|
||||||
|
cerr << pins[idx]->get_fileline() << ": warning: output port "
|
||||||
|
<< prts[0]->name() << " is coerced to inout." << endl;
|
||||||
|
}
|
||||||
|
|
||||||
// Elaborate the expression that connects to the
|
// Elaborate the expression that connects to the
|
||||||
// module[s] port. sig is the thing outside the module
|
// module[s] port. sig is the thing outside the module
|
||||||
// that connects to the port.
|
// that connects to the port.
|
||||||
|
|
@ -2000,7 +2014,7 @@ void PGModule::elaborate_udp_(Design*des, PUdp*udp, NetScope*scope) const
|
||||||
PDelays tmp_del;
|
PDelays tmp_del;
|
||||||
tmp_del.set_delays(overrides_, false);
|
tmp_del.set_delays(overrides_, false);
|
||||||
tmp_del.eval_delays(des, scope, rise_expr, fall_expr,
|
tmp_del.eval_delays(des, scope, rise_expr, fall_expr,
|
||||||
decay_expr);
|
decay_expr, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2325,7 +2339,8 @@ NetExpr* PAssign_::elaborate_rval_(Design*des, NetScope*scope,
|
||||||
NetExpr* PAssign_::elaborate_rval_(Design*des, NetScope*scope,
|
NetExpr* PAssign_::elaborate_rval_(Design*des, NetScope*scope,
|
||||||
ivl_type_t lv_net_type,
|
ivl_type_t lv_net_type,
|
||||||
ivl_variable_type_t lv_type,
|
ivl_variable_type_t lv_type,
|
||||||
unsigned lv_width) const
|
unsigned lv_width,
|
||||||
|
bool force_unsigned) const
|
||||||
{
|
{
|
||||||
ivl_assert(*this, rval_);
|
ivl_assert(*this, rval_);
|
||||||
|
|
||||||
|
|
@ -2334,7 +2349,7 @@ NetExpr* PAssign_::elaborate_rval_(Design*des, NetScope*scope,
|
||||||
// should look into fixing calls to this method to pass a
|
// should look into fixing calls to this method to pass a
|
||||||
// net_type instead of the separate lv_width/lv_type values.
|
// net_type instead of the separate lv_width/lv_type values.
|
||||||
NetExpr*rv = elaborate_rval_expr(des, scope, lv_net_type, lv_type, lv_width,
|
NetExpr*rv = elaborate_rval_expr(des, scope, lv_net_type, lv_type, lv_width,
|
||||||
rval(), is_constant_);
|
rval(), is_constant_, force_unsigned);
|
||||||
|
|
||||||
if (!is_constant_ || !rv) return rv;
|
if (!is_constant_ || !rv) return rv;
|
||||||
|
|
||||||
|
|
@ -2452,10 +2467,35 @@ NetProc* PAssign::elaborate_compressed_(Design*des, NetScope*scope) const
|
||||||
NetAssign_*lv = elaborate_lval(des, scope);
|
NetAssign_*lv = elaborate_lval(des, scope);
|
||||||
if (lv == 0) return 0;
|
if (lv == 0) return 0;
|
||||||
|
|
||||||
NetExpr*rv = elaborate_rval_(des, scope, 0, lv->expr_type(), count_lval_width(lv));
|
// Compressed assignments should behave identically to the
|
||||||
|
// equivalent uncompressed assignments. This means we need
|
||||||
|
// to take the type of the LHS into account when determining
|
||||||
|
// the type of the RHS expression.
|
||||||
|
bool force_unsigned;
|
||||||
|
switch (op_) {
|
||||||
|
case 'l':
|
||||||
|
case 'r':
|
||||||
|
case 'R':
|
||||||
|
// The right-hand operand of shift operations is
|
||||||
|
// self-determined.
|
||||||
|
force_unsigned = false;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
force_unsigned = !lv->get_signed();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
NetExpr*rv = elaborate_rval_(des, scope, 0, lv->expr_type(),
|
||||||
|
count_lval_width(lv), force_unsigned);
|
||||||
if (rv == 0) return 0;
|
if (rv == 0) return 0;
|
||||||
|
|
||||||
NetAssign*cur = new NetAssign(lv, op_, rv);
|
// The ivl_target API doesn't support signalling the type
|
||||||
|
// of a lval, so convert arithmetic shifts into logical
|
||||||
|
// shifts now if the lval is unsigned.
|
||||||
|
char op = op_;
|
||||||
|
if ((op == 'R') && !lv->get_signed())
|
||||||
|
op = 'r';
|
||||||
|
|
||||||
|
NetAssign*cur = new NetAssign(lv, op, rv);
|
||||||
cur->set_line(*this);
|
cur->set_line(*this);
|
||||||
|
|
||||||
return cur;
|
return cur;
|
||||||
|
|
@ -2868,14 +2908,27 @@ NetProc* PBlock::elaborate(Design*des, NetScope*scope) const
|
||||||
des->errors += 1;
|
des->errors += 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(nscope);
|
assert(nscope);
|
||||||
|
|
||||||
elaborate_behaviors_(des, nscope);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NetBlock*cur = new NetBlock(type, nscope);
|
NetBlock*cur = new NetBlock(type, nscope);
|
||||||
|
|
||||||
|
if (nscope) {
|
||||||
|
// Handle any variable initialization statements in this scope.
|
||||||
|
// For automatic scopes these statements need to be executed
|
||||||
|
// each time the block is entered, so add them to the main
|
||||||
|
// block. For static scopes, put them in a separate process
|
||||||
|
// that will be executed at the start of simulation.
|
||||||
|
if (nscope->is_auto()) {
|
||||||
|
for (unsigned idx = 0; idx < var_inits.size(); idx += 1) {
|
||||||
|
NetProc*tmp = var_inits[idx]->elaborate(des, nscope);
|
||||||
|
if (tmp) cur->append(tmp);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
elaborate_var_inits_(des, nscope);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (nscope == 0)
|
if (nscope == 0)
|
||||||
nscope = scope;
|
nscope = scope;
|
||||||
|
|
||||||
|
|
@ -3778,7 +3831,9 @@ NetProc* PCallTask::elaborate_build_call_(Design*des, NetScope*scope,
|
||||||
expression that can be a target to a procedural
|
expression that can be a target to a procedural
|
||||||
assignment, including a memory word. */
|
assignment, including a memory word. */
|
||||||
|
|
||||||
for (unsigned idx = 0 ; idx < parm_count ; idx += 1) {
|
for (unsigned idx = use_this?1:0 ; idx < parm_count ; idx += 1) {
|
||||||
|
|
||||||
|
size_t parms_idx = use_this? idx-1 : idx;
|
||||||
|
|
||||||
NetNet*port = def->port(idx);
|
NetNet*port = def->port(idx);
|
||||||
|
|
||||||
|
|
@ -3794,12 +3849,12 @@ NetProc* PCallTask::elaborate_build_call_(Design*des, NetScope*scope,
|
||||||
message. Note that the elaborate_lval method already
|
message. Note that the elaborate_lval method already
|
||||||
printed a detailed message for the latter case. */
|
printed a detailed message for the latter case. */
|
||||||
NetAssign_*lv = 0;
|
NetAssign_*lv = 0;
|
||||||
if (idx < parms_.size() && parms_[idx]) {
|
if (parms_idx < parms_.size() && parms_[parms_idx]) {
|
||||||
lv = parms_[idx]->elaborate_lval(des, scope, false, false);
|
lv = parms_[parms_idx]->elaborate_lval(des, scope, false, false);
|
||||||
if (lv == 0) {
|
if (lv == 0) {
|
||||||
cerr << parms_[idx]->get_fileline() << ": error: "
|
cerr << parms_[parms_idx]->get_fileline() << ": error: "
|
||||||
<< "I give up on task port " << (idx+1)
|
<< "I give up on task port " << (idx+1)
|
||||||
<< " expression: " << *parms_[idx] << endl;
|
<< " expression: " << *parms_[parms_idx] << endl;
|
||||||
}
|
}
|
||||||
} else if (port->port_type() == NetNet::POUTPUT) {
|
} else if (port->port_type() == NetNet::POUTPUT) {
|
||||||
// Output ports were skipped earlier, so
|
// Output ports were skipped earlier, so
|
||||||
|
|
@ -4997,7 +5052,6 @@ void PFunction::elaborate(Design*des, NetScope*scope) const
|
||||||
des->errors += 1;
|
des->errors += 1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(def);
|
assert(def);
|
||||||
|
|
||||||
ivl_assert(*this, statement_);
|
ivl_assert(*this, statement_);
|
||||||
|
|
@ -5010,6 +5064,31 @@ void PFunction::elaborate(Design*des, NetScope*scope) const
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle any variable initialization statements in this scope.
|
||||||
|
// For automatic functions, these statements need to be executed
|
||||||
|
// each time the function is called, so insert them at the start
|
||||||
|
// of the elaborated definition. For static functions, put them
|
||||||
|
// in a separate process that will be executed before the start
|
||||||
|
// of simulation.
|
||||||
|
if (is_auto_) {
|
||||||
|
// Get the NetBlock of the statement. If it is not a
|
||||||
|
// NetBlock then create one to wrap the initialization
|
||||||
|
// statements and the original statement.
|
||||||
|
NetBlock*blk = dynamic_cast<NetBlock*> (st);
|
||||||
|
if ((blk == 0) && (var_inits.size() > 0)) {
|
||||||
|
blk = new NetBlock(NetBlock::SEQU, scope);
|
||||||
|
blk->set_line(*this);
|
||||||
|
blk->append(st);
|
||||||
|
st = blk;
|
||||||
|
}
|
||||||
|
for (unsigned idx = var_inits.size(); idx > 0; idx -= 1) {
|
||||||
|
NetProc*tmp = var_inits[idx-1]->elaborate(des, scope);
|
||||||
|
if (tmp) blk->prepend(tmp);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
elaborate_var_inits_(des, scope);
|
||||||
|
}
|
||||||
|
|
||||||
def->set_proc(st);
|
def->set_proc(st);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -5172,11 +5251,6 @@ NetProc* PReturn::elaborate(Design*des, NetScope*scope) const
|
||||||
|
|
||||||
void PTask::elaborate(Design*des, NetScope*task) const
|
void PTask::elaborate(Design*des, NetScope*task) const
|
||||||
{
|
{
|
||||||
// Elaborate any processes that are part of this scope that
|
|
||||||
// aren't the definition itself. This can happen, for example,
|
|
||||||
// with variable initialization statements in this scope.
|
|
||||||
elaborate_behaviors_(des, task);
|
|
||||||
|
|
||||||
NetTaskDef*def = task->task_def();
|
NetTaskDef*def = task->task_def();
|
||||||
assert(def);
|
assert(def);
|
||||||
|
|
||||||
|
|
@ -5195,6 +5269,31 @@ void PTask::elaborate(Design*des, NetScope*task) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle any variable initialization statements in this scope.
|
||||||
|
// For automatic tasks , these statements need to be executed
|
||||||
|
// each time the task is called, so insert them at the start
|
||||||
|
// of the elaborated definition. For static tasks, put them
|
||||||
|
// in a separate process that will be executed before the start
|
||||||
|
// of simulation.
|
||||||
|
if (is_auto_) {
|
||||||
|
// Get the NetBlock of the statement. If it is not a
|
||||||
|
// NetBlock then create one to wrap the initialization
|
||||||
|
// statements and the original statement.
|
||||||
|
NetBlock*blk = dynamic_cast<NetBlock*> (st);
|
||||||
|
if ((blk == 0) && (var_inits.size() > 0)) {
|
||||||
|
blk = new NetBlock(NetBlock::SEQU, task);
|
||||||
|
blk->set_line(*this);
|
||||||
|
blk->append(st);
|
||||||
|
st = blk;
|
||||||
|
}
|
||||||
|
for (unsigned idx = var_inits.size(); idx > 0; idx -= 1) {
|
||||||
|
NetProc*tmp = var_inits[idx-1]->elaborate(des, task);
|
||||||
|
if (tmp) blk->prepend(tmp);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
elaborate_var_inits_(des, task);
|
||||||
|
}
|
||||||
|
|
||||||
def->set_proc(st);
|
def->set_proc(st);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -5651,6 +5750,10 @@ bool Module::elaborate(Design*des, NetScope*scope) const
|
||||||
(*gt)->elaborate(des, scope);
|
(*gt)->elaborate(des, scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Elaborate the variable initialization statements, making a
|
||||||
|
// single initial process out of them.
|
||||||
|
result_flag &= elaborate_var_inits_(des, scope);
|
||||||
|
|
||||||
// Elaborate the behaviors, making processes out of them. This
|
// Elaborate the behaviors, making processes out of them. This
|
||||||
// involves scanning the PProcess* list, creating a NetProcTop
|
// involves scanning the PProcess* list, creating a NetProcTop
|
||||||
// for each process.
|
// for each process.
|
||||||
|
|
@ -5841,6 +5944,8 @@ bool PGenerate::elaborate_(Design*des, NetScope*scope) const
|
||||||
for (gates_it_t cur = gates.begin() ; cur != gates.end() ; ++ cur )
|
for (gates_it_t cur = gates.begin() ; cur != gates.end() ; ++ cur )
|
||||||
(*cur)->elaborate(des, scope);
|
(*cur)->elaborate(des, scope);
|
||||||
|
|
||||||
|
elaborate_var_inits_(des, scope);
|
||||||
|
|
||||||
typedef list<PProcess*>::const_iterator proc_it_t;
|
typedef list<PProcess*>::const_iterator proc_it_t;
|
||||||
for (proc_it_t cur = behaviors.begin(); cur != behaviors.end(); ++ cur )
|
for (proc_it_t cur = behaviors.begin(); cur != behaviors.end(); ++ cur )
|
||||||
(*cur)->elaborate(des, scope);
|
(*cur)->elaborate(des, scope);
|
||||||
|
|
@ -5876,6 +5981,44 @@ bool PScope::elaborate_behaviors_(Design*des, NetScope*scope) const
|
||||||
return result_flag;
|
return result_flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool LexicalScope::elaborate_var_inits_(Design*des, NetScope*scope) const
|
||||||
|
{
|
||||||
|
if (var_inits.size() == 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
NetProc*proc = 0;
|
||||||
|
if (var_inits.size() == 1) {
|
||||||
|
proc = var_inits[0]->elaborate(des, scope);
|
||||||
|
} else {
|
||||||
|
NetBlock*blk = new NetBlock(NetBlock::SEQU, 0);
|
||||||
|
bool flag = true;
|
||||||
|
for (unsigned idx = 0; idx < var_inits.size(); idx += 1) {
|
||||||
|
NetProc*tmp = var_inits[idx]->elaborate(des, scope);
|
||||||
|
if (tmp)
|
||||||
|
blk->append(tmp);
|
||||||
|
else
|
||||||
|
flag = false;
|
||||||
|
}
|
||||||
|
if (flag) proc = blk;
|
||||||
|
}
|
||||||
|
if (proc == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
NetProcTop*top = new NetProcTop(scope, IVL_PR_INITIAL, proc);
|
||||||
|
if (const LineInfo*li = dynamic_cast<const LineInfo*>(this)) {
|
||||||
|
top->set_line(*li);
|
||||||
|
}
|
||||||
|
if (gn_system_verilog()) {
|
||||||
|
top->attribute(perm_string::literal("_ivl_schedule_init"),
|
||||||
|
verinum(1));
|
||||||
|
}
|
||||||
|
des->add_process(top);
|
||||||
|
|
||||||
|
scope->set_var_init(proc);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
class elaborate_package_t : public elaborator_work_item_t {
|
class elaborate_package_t : public elaborator_work_item_t {
|
||||||
public:
|
public:
|
||||||
elaborate_package_t(Design*d, NetScope*scope, PPackage*p)
|
elaborate_package_t(Design*d, NetScope*scope, PPackage*p)
|
||||||
|
|
@ -6109,6 +6252,7 @@ Design* elaborate(list<perm_string>roots)
|
||||||
ivl_assert(*pac->second, pac->first == pac->second->pscope_name());
|
ivl_assert(*pac->second, pac->first == pac->second->pscope_name());
|
||||||
NetScope*scope = des->make_package_scope(pac->first);
|
NetScope*scope = des->make_package_scope(pac->first);
|
||||||
scope->set_line(pac->second);
|
scope->set_line(pac->second);
|
||||||
|
set_scope_timescale(des, scope, pac->second);
|
||||||
|
|
||||||
elaborator_work_item_t*es = new elaborate_package_t(des, scope, pac->second);
|
elaborator_work_item_t*es = new elaborate_package_t(des, scope, pac->second);
|
||||||
des->elaboration_work_list.push_back(es);
|
des->elaboration_work_list.push_back(es);
|
||||||
|
|
@ -6145,11 +6289,7 @@ Design* elaborate(list<perm_string>roots)
|
||||||
// Collect some basic properties of this scope from the
|
// Collect some basic properties of this scope from the
|
||||||
// Module definition.
|
// Module definition.
|
||||||
scope->set_line(rmod);
|
scope->set_line(rmod);
|
||||||
scope->time_unit(rmod->time_unit);
|
set_scope_timescale(des, scope, rmod);
|
||||||
scope->time_precision(rmod->time_precision);
|
|
||||||
scope->time_from_timescale(rmod->time_from_timescale);
|
|
||||||
des->set_precision(rmod->time_precision);
|
|
||||||
|
|
||||||
|
|
||||||
// Save this scope, along with its definition, in the
|
// Save this scope, along with its definition, in the
|
||||||
// "root_elems" list for later passes.
|
// "root_elems" list for later passes.
|
||||||
|
|
|
||||||
8
emit.cc
8
emit.cc
|
|
@ -507,7 +507,6 @@ int Design::emit(struct target_t*tgt) const
|
||||||
for (map<NetScope*,PTaskFunc*>::const_iterator scope = root_tasks_.begin()
|
for (map<NetScope*,PTaskFunc*>::const_iterator scope = root_tasks_.begin()
|
||||||
; scope != root_tasks_.end() ; ++ scope) {
|
; scope != root_tasks_.end() ; ++ scope) {
|
||||||
scope->first->emit_scope(tgt);
|
scope->first->emit_scope(tgt);
|
||||||
scope->first->emit_defs(tgt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// enumerate package scopes
|
// enumerate package scopes
|
||||||
|
|
@ -521,7 +520,6 @@ int Design::emit(struct target_t*tgt) const
|
||||||
const NetScope*use_scope = cur->second->class_scope();
|
const NetScope*use_scope = cur->second->class_scope();
|
||||||
cur->second->emit_scope(tgt);
|
cur->second->emit_scope(tgt);
|
||||||
tgt->class_type(use_scope, cur->second);
|
tgt->class_type(use_scope, cur->second);
|
||||||
cur->second->emit_defs(tgt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// enumerate root scopes
|
// enumerate root scopes
|
||||||
|
|
@ -548,6 +546,12 @@ int Design::emit(struct target_t*tgt) const
|
||||||
|
|
||||||
// emit task and function definitions
|
// emit task and function definitions
|
||||||
bool tasks_rc = true;
|
bool tasks_rc = true;
|
||||||
|
for (map<NetScope*,PTaskFunc*>::const_iterator scope = root_tasks_.begin()
|
||||||
|
; scope != root_tasks_.end() ; ++ scope)
|
||||||
|
tasks_rc &= scope->first->emit_defs(tgt);
|
||||||
|
for (map<perm_string,netclass_t*>::const_iterator cur = classes_.begin()
|
||||||
|
; cur != classes_.end() ; ++cur)
|
||||||
|
tasks_rc &= cur->second->emit_defs(tgt);
|
||||||
for (map<perm_string,NetScope*>::const_iterator scope = packages_.begin()
|
for (map<perm_string,NetScope*>::const_iterator scope = packages_.begin()
|
||||||
; scope != packages_.end() ; ++ scope )
|
; scope != packages_.end() ; ++ scope )
|
||||||
tasks_rc &= scope->second->emit_defs(tgt);
|
tasks_rc &= scope->second->emit_defs(tgt);
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
%option prefix="yy"
|
%option prefix="yy"
|
||||||
%{
|
%{
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1999-2015 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 1999-2016 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -153,9 +153,29 @@ static void ifdef_leave(void)
|
||||||
size_t rc = fread(buf, 1, max_size, istack->file); \
|
size_t rc = fread(buf, 1, max_size, istack->file); \
|
||||||
result = (rc == 0) ? YY_NULL : rc; \
|
result = (rc == 0) ? YY_NULL : rc; \
|
||||||
} else { \
|
} else { \
|
||||||
if (*istack->str == 0) \
|
/* We are expanding a macro. Handle the SV macro escape \
|
||||||
|
sequences. There doesn't seem to be any good reason \
|
||||||
|
not to allow them in traditional Verilog as well. */ \
|
||||||
|
while ((istack->str[0] == '`') && \
|
||||||
|
(istack->str[1] == '`')) { \
|
||||||
|
istack->str += 2; \
|
||||||
|
} \
|
||||||
|
if (*istack->str == 0) { \
|
||||||
result = YY_NULL; \
|
result = YY_NULL; \
|
||||||
else { \
|
} else if ((istack->str[0] == '`') && \
|
||||||
|
(istack->str[1] == '"')) { \
|
||||||
|
istack->str += 2; \
|
||||||
|
buf[0] = '"'; \
|
||||||
|
result = 1; \
|
||||||
|
} else if ((istack->str[0] == '`') && \
|
||||||
|
(istack->str[1] == '\\')&& \
|
||||||
|
(istack->str[2] == '`') && \
|
||||||
|
(istack->str[3] == '"')) { \
|
||||||
|
istack->str += 4; \
|
||||||
|
buf[0] = '\\'; \
|
||||||
|
buf[1] = '"'; \
|
||||||
|
result = 2; \
|
||||||
|
} else { \
|
||||||
buf[0] = *istack->str++; \
|
buf[0] = *istack->str++; \
|
||||||
result = 1; \
|
result = 1; \
|
||||||
} \
|
} \
|
||||||
|
|
@ -242,12 +262,6 @@ keywords (include|define|undef|ifdef|ifndef|else|elseif|endif)
|
||||||
if (macro_needs_args(yytext+1)) yy_push_state(MA_START); else do_expand(0);
|
if (macro_needs_args(yytext+1)) yy_push_state(MA_START); else do_expand(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* `" overrides the usual lexical meaning of " and `\`" indicates
|
|
||||||
that the expansion should include the escape sequence \".
|
|
||||||
*/
|
|
||||||
`\" { fputc('"', yyout); }
|
|
||||||
`\\`\" { fprintf(yyout, "\\\""); }
|
|
||||||
|
|
||||||
/* Strings do not contain preprocessor directives, but can expand
|
/* Strings do not contain preprocessor directives, but can expand
|
||||||
* macros. If that happens, they get expanded in the context of the
|
* macros. If that happens, they get expanded in the context of the
|
||||||
* string.
|
* string.
|
||||||
|
|
@ -514,17 +528,10 @@ keywords (include|define|undef|ifdef|ifndef|else|elseif|endif)
|
||||||
do_expand(0);
|
do_expand(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Stringified version of macro expansion. If the sequence `` is
|
/* Stringified version of macro expansion. This is an Icarus extension.
|
||||||
* encountered inside a macro definition, we use the SystemVerilog
|
When expanding macro text, the SV usage of `` takes precedence. */
|
||||||
* handling of ignoring it so that identifiers can be constructed
|
|
||||||
* from arguments. If istack->file is NULL, we are reading text
|
|
||||||
* produced from a macro, so use SystemVerilog's handling;
|
|
||||||
* otherwise, use the special Icarus handling.
|
|
||||||
*/
|
|
||||||
``[a-zA-Z_][a-zA-Z0-9_$]* {
|
``[a-zA-Z_][a-zA-Z0-9_$]* {
|
||||||
if (istack->file == NULL)
|
assert(istack->file);
|
||||||
fprintf(yyout, "%s", yytext+2);
|
|
||||||
else {
|
|
||||||
assert(do_expand_stringify_flag == 0);
|
assert(do_expand_stringify_flag == 0);
|
||||||
do_expand_stringify_flag = 1;
|
do_expand_stringify_flag = 1;
|
||||||
fputc('"', yyout);
|
fputc('"', yyout);
|
||||||
|
|
@ -532,11 +539,8 @@ keywords (include|define|undef|ifdef|ifndef|else|elseif|endif)
|
||||||
yy_push_state(MA_START);
|
yy_push_state(MA_START);
|
||||||
else
|
else
|
||||||
do_expand(0);
|
do_expand(0);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
`` { if (istack->file != NULL) ECHO; }
|
|
||||||
|
|
||||||
<MA_START>\( { BEGIN(MA_ADD); macro_start_args(); }
|
<MA_START>\( { BEGIN(MA_ADD); macro_start_args(); }
|
||||||
|
|
||||||
<MA_START>{W} {}
|
<MA_START>{W} {}
|
||||||
|
|
|
||||||
|
|
@ -453,7 +453,7 @@ TU [munpf]
|
||||||
return BASED_NUMBER;
|
return BASED_NUMBER;
|
||||||
}
|
}
|
||||||
\'[01xzXZ] {
|
\'[01xzXZ] {
|
||||||
if (generation_flag < GN_VER2005_SV) {
|
if (!gn_system_verilog()) {
|
||||||
cerr << yylloc.text << ":" << yylloc.first_line << ": warning: "
|
cerr << yylloc.text << ":" << yylloc.first_line << ": warning: "
|
||||||
<< "Using SystemVerilog 'N bit vector. Use at least "
|
<< "Using SystemVerilog 'N bit vector. Use at least "
|
||||||
<< "-g2005-sv to remove this warning." << endl;
|
<< "-g2005-sv to remove this warning." << endl;
|
||||||
|
|
@ -479,7 +479,7 @@ TU [munpf]
|
||||||
|
|
||||||
/* This rule handles scaled time values for SystemVerilog. */
|
/* This rule handles scaled time values for SystemVerilog. */
|
||||||
[0-9][0-9_]*(\.[0-9][0-9_]*)?{TU}?s {
|
[0-9][0-9_]*(\.[0-9][0-9_]*)?{TU}?s {
|
||||||
if(generation_flag & (GN_VER2005_SV | GN_VER2009 | GN_VER2012)) {
|
if (gn_system_verilog()) {
|
||||||
yylval.text = strdupnew(yytext);
|
yylval.text = strdupnew(yytext);
|
||||||
return TIME_LITERAL;
|
return TIME_LITERAL;
|
||||||
} else REJECT; }
|
} else REJECT; }
|
||||||
|
|
@ -857,7 +857,7 @@ verinum*make_unsized_binary(const char*txt)
|
||||||
ptr += 1;
|
ptr += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert((tolower(*ptr) == 'b') || (generation_flag >= GN_VER2005_SV));
|
assert((tolower(*ptr) == 'b') || gn_system_verilog());
|
||||||
if (tolower(*ptr) == 'b') {
|
if (tolower(*ptr) == 'b') {
|
||||||
ptr += 1;
|
ptr += 1;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
9
main.cc
9
main.cc
|
|
@ -108,6 +108,7 @@ bool gn_assertions_flag = true;
|
||||||
bool gn_io_range_error_flag = true;
|
bool gn_io_range_error_flag = true;
|
||||||
bool gn_strict_ca_eval_flag = false;
|
bool gn_strict_ca_eval_flag = false;
|
||||||
bool gn_strict_expr_width_flag = false;
|
bool gn_strict_expr_width_flag = false;
|
||||||
|
bool gn_shared_loop_index_flag = false;
|
||||||
bool gn_verilog_ams_flag = false;
|
bool gn_verilog_ams_flag = false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -344,6 +345,12 @@ static void process_generation_flag(const char*gen)
|
||||||
} else if (strcmp(gen,"no-strict-expr-width") == 0) {
|
} else if (strcmp(gen,"no-strict-expr-width") == 0) {
|
||||||
gn_strict_expr_width_flag = false;
|
gn_strict_expr_width_flag = false;
|
||||||
|
|
||||||
|
} else if (strcmp(gen,"shared-loop-index") == 0) {
|
||||||
|
gn_shared_loop_index_flag = true;
|
||||||
|
|
||||||
|
} else if (strcmp(gen,"no-shared-loop-index") == 0) {
|
||||||
|
gn_shared_loop_index_flag = false;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1111,7 +1118,7 @@ int main(int argc, char*argv[])
|
||||||
|
|
||||||
/* Decide if we are going to allow system functions to be called
|
/* Decide if we are going to allow system functions to be called
|
||||||
* as tasks. */
|
* as tasks. */
|
||||||
if (generation_flag >= GN_VER2005_SV) {
|
if (gn_system_verilog()) {
|
||||||
def_sfunc_as_task = IVL_SFUNC_AS_TASK_WARNING;
|
def_sfunc_as_task = IVL_SFUNC_AS_TASK_WARNING;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,8 @@ NetAssign_::NetAssign_(NetAssign_*n)
|
||||||
: nest_(n), sig_(0), word_(0), base_(0), sel_type_(IVL_SEL_OTHER)
|
: nest_(n), sig_(0), word_(0), base_(0), sel_type_(IVL_SEL_OTHER)
|
||||||
{
|
{
|
||||||
more = 0;
|
more = 0;
|
||||||
|
signed_ = false;
|
||||||
|
turn_sig_to_wire_on_release_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
NetAssign_::NetAssign_(NetNet*s)
|
NetAssign_::NetAssign_(NetNet*s)
|
||||||
|
|
@ -51,6 +53,7 @@ NetAssign_::NetAssign_(NetNet*s)
|
||||||
lwid_ = sig_->vector_width();
|
lwid_ = sig_->vector_width();
|
||||||
sig_->incr_lref();
|
sig_->incr_lref();
|
||||||
more = 0;
|
more = 0;
|
||||||
|
signed_ = false;
|
||||||
turn_sig_to_wire_on_release_ = false;
|
turn_sig_to_wire_on_release_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
152
net_func_eval.cc
152
net_func_eval.cc
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2012-2013 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2012-2016 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -88,6 +88,10 @@ NetExpr* NetFuncDef::evaluate_function(const LineInfo&loc, const std::vector<Net
|
||||||
// fills in the context_map with local variables held by the scope.
|
// fills in the context_map with local variables held by the scope.
|
||||||
scope()->evaluate_function_find_locals(loc, context_map);
|
scope()->evaluate_function_find_locals(loc, context_map);
|
||||||
|
|
||||||
|
// Execute any variable initialization statements.
|
||||||
|
if (const NetProc*init_proc = scope()->var_init())
|
||||||
|
init_proc->evaluate_function(loc, context_map);
|
||||||
|
|
||||||
if (debug_eval_tree && proc_==0) {
|
if (debug_eval_tree && proc_==0) {
|
||||||
cerr << loc.get_fileline() << ": NetFuncDef::evaluate_function: "
|
cerr << loc.get_fileline() << ": NetFuncDef::evaluate_function: "
|
||||||
<< "Function " << scope_path(scope())
|
<< "Function " << scope_path(scope())
|
||||||
|
|
@ -209,6 +213,98 @@ bool NetProc::evaluate_function(const LineInfo&,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NetAssign::eval_func_lval_op_real_(const LineInfo&loc,
|
||||||
|
verireal&lv, verireal&rv) const
|
||||||
|
{
|
||||||
|
switch (op_) {
|
||||||
|
case '+':
|
||||||
|
lv = lv + rv;
|
||||||
|
break;
|
||||||
|
case '-':
|
||||||
|
lv = lv - rv;
|
||||||
|
break;
|
||||||
|
case '*':
|
||||||
|
lv = lv * rv;
|
||||||
|
break;
|
||||||
|
case '/':
|
||||||
|
lv = lv / rv;
|
||||||
|
break;
|
||||||
|
case '%':
|
||||||
|
lv = lv % rv;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
cerr << "Illegal assignment operator: "
|
||||||
|
<< human_readable_op(op_) << endl;
|
||||||
|
ivl_assert(loc, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NetAssign::eval_func_lval_op_(const LineInfo&loc,
|
||||||
|
verinum&lv, verinum&rv) const
|
||||||
|
{
|
||||||
|
unsigned lv_width = lv.len();
|
||||||
|
bool lv_sign = lv.has_sign();
|
||||||
|
switch (op_) {
|
||||||
|
case 'l':
|
||||||
|
case 'R':
|
||||||
|
// The left operand is self-determined.
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
// The left operand is self-determined, but we need to
|
||||||
|
// cast it to unsigned to get a logical shift.
|
||||||
|
lv.has_sign(false);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// The left operand must be cast to the expression type/size
|
||||||
|
lv.has_sign(rv.has_sign());
|
||||||
|
lv = cast_to_width(lv, rv.len());
|
||||||
|
}
|
||||||
|
switch (op_) {
|
||||||
|
case '+':
|
||||||
|
lv = lv + rv;
|
||||||
|
break;
|
||||||
|
case '-':
|
||||||
|
lv = lv - rv;
|
||||||
|
break;
|
||||||
|
case '*':
|
||||||
|
lv = lv * rv;
|
||||||
|
break;
|
||||||
|
case '/':
|
||||||
|
lv = lv / rv;
|
||||||
|
break;
|
||||||
|
case '%':
|
||||||
|
lv = lv % rv;
|
||||||
|
break;
|
||||||
|
case '&':
|
||||||
|
for (unsigned idx = 0 ; idx < lv.len() ; idx += 1)
|
||||||
|
lv.set(idx, lv[idx] & rv[idx]);
|
||||||
|
break;
|
||||||
|
case '|':
|
||||||
|
for (unsigned idx = 0 ; idx < lv.len() ; idx += 1)
|
||||||
|
lv.set(idx, lv[idx] | rv[idx]);
|
||||||
|
break;
|
||||||
|
case '^':
|
||||||
|
for (unsigned idx = 0 ; idx < lv.len() ; idx += 1)
|
||||||
|
lv.set(idx, lv[idx] ^ rv[idx]);
|
||||||
|
break;
|
||||||
|
case 'l':
|
||||||
|
lv = lv << rv.as_unsigned();
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
lv = lv >> rv.as_unsigned();
|
||||||
|
break;
|
||||||
|
case 'R':
|
||||||
|
lv = lv >> rv.as_unsigned();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
cerr << "Illegal assignment operator: "
|
||||||
|
<< human_readable_op(op_) << endl;
|
||||||
|
ivl_assert(loc, 0);
|
||||||
|
}
|
||||||
|
lv = cast_to_width(lv, lv_width);
|
||||||
|
lv.has_sign(lv_sign);
|
||||||
|
}
|
||||||
|
|
||||||
bool NetAssign::eval_func_lval_(const LineInfo&loc,
|
bool NetAssign::eval_func_lval_(const LineInfo&loc,
|
||||||
map<perm_string,LocalVar>&context_map,
|
map<perm_string,LocalVar>&context_map,
|
||||||
const NetAssign_*lval, NetExpr*rval_result) const
|
const NetAssign_*lval, NetExpr*rval_result) const
|
||||||
|
|
@ -269,18 +365,55 @@ bool NetAssign::eval_func_lval_(const LineInfo&loc,
|
||||||
ivl_assert(loc, base + lval->lwidth() <= old_lval->expr_width());
|
ivl_assert(loc, base + lval->lwidth() <= old_lval->expr_width());
|
||||||
|
|
||||||
NetEConst*lval_const = dynamic_cast<NetEConst*>(old_lval);
|
NetEConst*lval_const = dynamic_cast<NetEConst*>(old_lval);
|
||||||
|
ivl_assert(loc, lval_const);
|
||||||
verinum lval_v = lval_const->value();
|
verinum lval_v = lval_const->value();
|
||||||
NetEConst*rval_const = dynamic_cast<NetEConst*>(rval_result);
|
NetEConst*rval_const = dynamic_cast<NetEConst*>(rval_result);
|
||||||
verinum rval_v = cast_to_width(rval_const->value(), lval->lwidth());
|
ivl_assert(loc, rval_const);
|
||||||
|
verinum rval_v = rval_const->value();
|
||||||
|
|
||||||
for (unsigned idx = 0 ; idx < rval_v.len() ; idx += 1)
|
verinum lpart(verinum::Vx, lval->lwidth());
|
||||||
lval_v.set(idx+base, rval_v[idx]);
|
if (op_) {
|
||||||
|
for (unsigned idx = 0 ; idx < lpart.len() ; idx += 1)
|
||||||
|
lpart.set(idx, lval_v[base+idx]);
|
||||||
|
|
||||||
|
eval_func_lval_op_(loc, lpart, rval_v);
|
||||||
|
} else {
|
||||||
|
lpart = cast_to_width(rval_v, lval->lwidth());
|
||||||
|
}
|
||||||
|
for (unsigned idx = 0 ; idx < lpart.len() ; idx += 1)
|
||||||
|
lval_v.set(idx+base, lpart[idx]);
|
||||||
|
|
||||||
delete base_result;
|
delete base_result;
|
||||||
delete rval_result;
|
delete rval_result;
|
||||||
rval_result = new NetEConst(lval_v);
|
rval_result = new NetEConst(lval_v);
|
||||||
} else {
|
} else {
|
||||||
|
if (op_ == 0) {
|
||||||
rval_result = fix_assign_value(lval->sig(), rval_result);
|
rval_result = fix_assign_value(lval->sig(), rval_result);
|
||||||
|
} else if (dynamic_cast<NetECReal*>(rval_result)) {
|
||||||
|
NetECReal*lval_const = dynamic_cast<NetECReal*>(old_lval);
|
||||||
|
ivl_assert(loc, lval_const);
|
||||||
|
verireal lval_r = lval_const->value();
|
||||||
|
NetECReal*rval_const = dynamic_cast<NetECReal*>(rval_result);
|
||||||
|
ivl_assert(loc, rval_const);
|
||||||
|
verireal rval_r = rval_const->value();
|
||||||
|
|
||||||
|
eval_func_lval_op_real_(loc, lval_r, rval_r);
|
||||||
|
|
||||||
|
delete rval_result;
|
||||||
|
rval_result = new NetECReal(lval_r);
|
||||||
|
} else {
|
||||||
|
NetEConst*lval_const = dynamic_cast<NetEConst*>(old_lval);
|
||||||
|
ivl_assert(loc, lval_const);
|
||||||
|
verinum lval_v = lval_const->value();
|
||||||
|
NetEConst*rval_const = dynamic_cast<NetEConst*>(rval_result);
|
||||||
|
ivl_assert(loc, rval_const);
|
||||||
|
verinum rval_v = rval_const->value();
|
||||||
|
|
||||||
|
eval_func_lval_op_(loc, lval_v, rval_v);
|
||||||
|
|
||||||
|
delete rval_result;
|
||||||
|
rval_result = new NetEConst(lval_v);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (old_lval)
|
if (old_lval)
|
||||||
|
|
@ -318,6 +451,13 @@ bool NetAssign::evaluate_function(const LineInfo&loc,
|
||||||
NetEConst*rval_const = dynamic_cast<NetEConst*>(rval_result);
|
NetEConst*rval_const = dynamic_cast<NetEConst*>(rval_result);
|
||||||
ivl_assert(*this, rval_const);
|
ivl_assert(*this, rval_const);
|
||||||
|
|
||||||
|
if (op_) {
|
||||||
|
cerr << get_fileline() << ": sorry: Assignment operators "
|
||||||
|
"inside a constant function are not currently "
|
||||||
|
"supported if the LHS is a concatenation." << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
verinum rval_full = rval_const->value();
|
verinum rval_full = rval_const->value();
|
||||||
delete rval_result;
|
delete rval_result;
|
||||||
|
|
||||||
|
|
@ -369,6 +509,10 @@ bool NetBlock::evaluate_function(const LineInfo&loc,
|
||||||
// Now collect the new locals.
|
// Now collect the new locals.
|
||||||
subscope_->evaluate_function_find_locals(loc, local_context_map);
|
subscope_->evaluate_function_find_locals(loc, local_context_map);
|
||||||
use_local_context_map = true;
|
use_local_context_map = true;
|
||||||
|
|
||||||
|
// Execute any variable initialization statements.
|
||||||
|
if (const NetProc*init_proc = subscope_->var_init())
|
||||||
|
init_proc->evaluate_function(loc, local_context_map);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now use the local context map if there is any local
|
// Now use the local context map if there is any local
|
||||||
|
|
|
||||||
14
net_link.cc
14
net_link.cc
|
|
@ -311,6 +311,20 @@ void Nexus::count_io(unsigned&inp, unsigned&out) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Nexus::has_floating_input() const
|
||||||
|
{
|
||||||
|
bool found_input = false;
|
||||||
|
for (const Link*cur = first_nlink() ; cur ; cur = cur->next_nlink()) {
|
||||||
|
if (cur->get_dir() == Link::OUTPUT)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (cur->get_dir() == Link::INPUT)
|
||||||
|
found_input = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return found_input;
|
||||||
|
}
|
||||||
|
|
||||||
bool Nexus::drivers_present() const
|
bool Nexus::drivers_present() const
|
||||||
{
|
{
|
||||||
for (const Link*cur = first_nlink() ; cur ; cur = cur->next_nlink()) {
|
for (const Link*cur = first_nlink() ; cur ; cur = cur->next_nlink()) {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2013 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2002-2016 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -427,6 +427,15 @@ NexusSet* NetForLoop::nex_input(bool rem_out)
|
||||||
result->add(*tmp);
|
result->add(*tmp);
|
||||||
delete tmp;
|
delete tmp;
|
||||||
|
|
||||||
|
if (gn_shared_loop_index_flag) {
|
||||||
|
tmp = new NexusSet();
|
||||||
|
for (unsigned idx = 0 ; idx < index_->pin_count() ; idx += 1)
|
||||||
|
tmp->add(index_->pin(idx).nexus(), 0, index_->vector_width());
|
||||||
|
|
||||||
|
result->rem(*tmp);
|
||||||
|
delete tmp;
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
11
net_proc.cc
11
net_proc.cc
|
|
@ -56,6 +56,17 @@ void NetBlock::append(NetProc*cur)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NetBlock::prepend(NetProc*cur)
|
||||||
|
{
|
||||||
|
if (last_ == 0) {
|
||||||
|
last_ = cur;
|
||||||
|
cur->next_ = cur;
|
||||||
|
} else {
|
||||||
|
cur->next_ = last_->next_;
|
||||||
|
last_->next_ = cur;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const NetProc* NetBlock::proc_first() const
|
const NetProc* NetBlock::proc_first() const
|
||||||
{
|
{
|
||||||
if (last_ == 0)
|
if (last_ == 0)
|
||||||
|
|
|
||||||
|
|
@ -139,6 +139,7 @@ NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t, bool nest,
|
||||||
time_from_timescale_ = false;
|
time_from_timescale_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var_init_ = 0;
|
||||||
switch (t) {
|
switch (t) {
|
||||||
case NetScope::TASK:
|
case NetScope::TASK:
|
||||||
task_ = 0;
|
task_ = 0;
|
||||||
|
|
|
||||||
|
|
@ -557,7 +557,7 @@ void NetNet::calculate_slice_widths_from_packed_dims_(void)
|
||||||
ivl_assert(*this, ! slice_wids_.empty());
|
ivl_assert(*this, ! slice_wids_.empty());
|
||||||
slice_wids_[0] = netrange_width(slice_dims_);
|
slice_wids_[0] = netrange_width(slice_dims_);
|
||||||
vector<netrange_t>::const_iterator cur = slice_dims_.begin();
|
vector<netrange_t>::const_iterator cur = slice_dims_.begin();
|
||||||
for (size_t idx = 1 ; idx < slice_wids_.size() ; idx += 1) {
|
for (size_t idx = 1 ; idx < slice_wids_.size() ; idx += 1, cur++) {
|
||||||
slice_wids_[idx] = slice_wids_[idx-1] / cur->width();
|
slice_wids_[idx] = slice_wids_[idx-1] / cur->width();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
25
netlist.h
25
netlist.h
|
|
@ -388,6 +388,10 @@ class Nexus {
|
||||||
is a variable, but also if this is a net with a force. */
|
is a variable, but also if this is a net with a force. */
|
||||||
bool assign_lval() const;
|
bool assign_lval() const;
|
||||||
|
|
||||||
|
/* This method returns true if there are any inputs
|
||||||
|
attached to this nexus but no drivers. */
|
||||||
|
bool has_floating_input() const;
|
||||||
|
|
||||||
/* This method returns true if there are any drivers
|
/* This method returns true if there are any drivers
|
||||||
(including variables) attached to this nexus. */
|
(including variables) attached to this nexus. */
|
||||||
bool drivers_present() const;
|
bool drivers_present() const;
|
||||||
|
|
@ -713,7 +717,7 @@ class NetNet : public NetObj, public PortType {
|
||||||
/* This method returns a reference to the packed dimensions
|
/* This method returns a reference to the packed dimensions
|
||||||
for the vector. These are arranged as a list where the
|
for the vector. These are arranged as a list where the
|
||||||
first range in the list (front) is the left-most range in
|
first range in the list (front) is the left-most range in
|
||||||
the verilog declaration. These packed dims are compressed
|
the Verilog declaration. These packed dims are compressed
|
||||||
to represent the dimensions of all the subtypes. */
|
to represent the dimensions of all the subtypes. */
|
||||||
const std::vector<netrange_t>& packed_dims() const { return slice_dims_; }
|
const std::vector<netrange_t>& packed_dims() const { return slice_dims_; }
|
||||||
|
|
||||||
|
|
@ -1020,6 +1024,13 @@ class NetScope : public Definitions, public Attrib {
|
||||||
TYPE type() const;
|
TYPE type() const;
|
||||||
void print_type(ostream&) const;
|
void print_type(ostream&) const;
|
||||||
|
|
||||||
|
// This provides a link to the variable initialisation process
|
||||||
|
// for use when evaluating a constant function. Note this is
|
||||||
|
// only used for static functions - the variable initialization
|
||||||
|
// for automatic functions is included in the function definition.
|
||||||
|
void set_var_init(const NetProc*proc) { var_init_ = proc; }
|
||||||
|
const NetProc* var_init() const { return var_init_; }
|
||||||
|
|
||||||
void set_task_def(NetTaskDef*);
|
void set_task_def(NetTaskDef*);
|
||||||
void set_func_def(NetFuncDef*);
|
void set_func_def(NetFuncDef*);
|
||||||
void set_class_def(netclass_t*);
|
void set_class_def(netclass_t*);
|
||||||
|
|
@ -1250,6 +1261,8 @@ class NetScope : public Definitions, public Attrib {
|
||||||
|
|
||||||
vector<PortInfo> ports_;
|
vector<PortInfo> ports_;
|
||||||
|
|
||||||
|
const NetProc*var_init_;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
NetTaskDef*task_;
|
NetTaskDef*task_;
|
||||||
NetFuncDef*func_;
|
NetFuncDef*func_;
|
||||||
|
|
@ -2732,6 +2745,12 @@ class NetAssign_ {
|
||||||
void set_property(const perm_string&name);
|
void set_property(const perm_string&name);
|
||||||
inline perm_string get_property(void) const { return member_; }
|
inline perm_string get_property(void) const { return member_; }
|
||||||
|
|
||||||
|
// Determine if the assigned object is signed or unsigned.
|
||||||
|
// This is used when determining the expression type for
|
||||||
|
// a compressed assignment statement.
|
||||||
|
bool get_signed() const { return signed_; }
|
||||||
|
void set_signed(bool flag) { signed_ = flag; }
|
||||||
|
|
||||||
// Get the width of the r-value that this node expects. This
|
// Get the width of the r-value that this node expects. This
|
||||||
// method accounts for the presence of the mux, so it is not
|
// method accounts for the presence of the mux, so it is not
|
||||||
// necessarily the same as the pin_count().
|
// necessarily the same as the pin_count().
|
||||||
|
|
@ -2782,6 +2801,7 @@ class NetAssign_ {
|
||||||
// member/property if signal is a class.
|
// member/property if signal is a class.
|
||||||
perm_string member_;
|
perm_string member_;
|
||||||
|
|
||||||
|
bool signed_;
|
||||||
bool turn_sig_to_wire_on_release_;
|
bool turn_sig_to_wire_on_release_;
|
||||||
// indexed part select base
|
// indexed part select base
|
||||||
NetExpr*base_;
|
NetExpr*base_;
|
||||||
|
|
@ -2849,6 +2869,8 @@ class NetAssign : public NetAssignBase {
|
||||||
map<perm_string,LocalVar>&ctx) const;
|
map<perm_string,LocalVar>&ctx) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void eval_func_lval_op_real_(const LineInfo&loc, verireal&lv, verireal&rv) const;
|
||||||
|
void eval_func_lval_op_(const LineInfo&loc, verinum&lv, verinum&rv) const;
|
||||||
bool eval_func_lval_(const LineInfo&loc, map<perm_string,LocalVar>&ctx,
|
bool eval_func_lval_(const LineInfo&loc, map<perm_string,LocalVar>&ctx,
|
||||||
const NetAssign_*lval, NetExpr*rval_result) const;
|
const NetAssign_*lval, NetExpr*rval_result) const;
|
||||||
|
|
||||||
|
|
@ -2895,6 +2917,7 @@ class NetBlock : public NetProc {
|
||||||
NetScope* subscope() const { return subscope_; }
|
NetScope* subscope() const { return subscope_; }
|
||||||
|
|
||||||
void append(NetProc*);
|
void append(NetProc*);
|
||||||
|
void prepend(NetProc*);
|
||||||
|
|
||||||
const NetProc*proc_first() const;
|
const NetProc*proc_first() const;
|
||||||
const NetProc*proc_next(const NetProc*cur) const;
|
const NetProc*proc_next(const NetProc*cur) const;
|
||||||
|
|
|
||||||
89
netmisc.cc
89
netmisc.cc
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2014 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2001-2016 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -203,7 +203,7 @@ static NetExpr* make_add_expr(NetExpr*expr, long val)
|
||||||
}
|
}
|
||||||
|
|
||||||
verinum val_v (val, expr->expr_width());
|
verinum val_v (val, expr->expr_width());
|
||||||
val_v.has_sign(true);
|
val_v.has_sign(expr->has_sign());
|
||||||
|
|
||||||
NetEConst*val_c = new NetEConst(val_v);
|
NetEConst*val_c = new NetEConst(val_v);
|
||||||
val_c->set_line(*expr);
|
val_c->set_line(*expr);
|
||||||
|
|
@ -236,7 +236,7 @@ static NetExpr* make_add_expr(const LineInfo*loc, NetExpr*expr1, NetExpr*expr2)
|
||||||
static NetExpr* make_sub_expr(long val, NetExpr*expr)
|
static NetExpr* make_sub_expr(long val, NetExpr*expr)
|
||||||
{
|
{
|
||||||
verinum val_v (val, expr->expr_width());
|
verinum val_v (val, expr->expr_width());
|
||||||
val_v.has_sign(true);
|
val_v.has_sign(expr->has_sign());
|
||||||
|
|
||||||
NetEConst*val_c = new NetEConst(val_v);
|
NetEConst*val_c = new NetEConst(val_v);
|
||||||
val_c->set_line(*expr);
|
val_c->set_line(*expr);
|
||||||
|
|
@ -249,7 +249,26 @@ static NetExpr* make_sub_expr(long val, NetExpr*expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Multiple an existing expression by a signed positive number.
|
* Subtract a signed constant from an existing expression.
|
||||||
|
*/
|
||||||
|
static NetExpr* make_sub_expr(NetExpr*expr, long val)
|
||||||
|
{
|
||||||
|
verinum val_v (val, expr->expr_width());
|
||||||
|
val_v.has_sign(expr->has_sign());
|
||||||
|
|
||||||
|
NetEConst*val_c = new NetEConst(val_v);
|
||||||
|
val_c->set_line(*expr);
|
||||||
|
|
||||||
|
NetEBAdd*res = new NetEBAdd('-', expr, val_c, expr->expr_width(),
|
||||||
|
expr->has_sign());
|
||||||
|
res->set_line(*expr);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Multiply an existing expression by a signed positive number.
|
||||||
* This does a lossless multiply, so the arguments will need to be
|
* This does a lossless multiply, so the arguments will need to be
|
||||||
* sized to match the output size.
|
* sized to match the output size.
|
||||||
*/
|
*/
|
||||||
|
|
@ -258,7 +277,7 @@ static NetExpr* make_mult_expr(NetExpr*expr, unsigned long val)
|
||||||
const unsigned val_wid = ceil(log2((double)val)) ;
|
const unsigned val_wid = ceil(log2((double)val)) ;
|
||||||
unsigned use_wid = expr->expr_width() + val_wid;
|
unsigned use_wid = expr->expr_width() + val_wid;
|
||||||
verinum val_v (val, use_wid);
|
verinum val_v (val, use_wid);
|
||||||
val_v.has_sign(true);
|
val_v.has_sign(expr->has_sign());
|
||||||
|
|
||||||
NetEConst*val_c = new NetEConst(val_v);
|
NetEConst*val_c = new NetEConst(val_v);
|
||||||
val_c->set_line(*expr);
|
val_c->set_line(*expr);
|
||||||
|
|
@ -434,17 +453,41 @@ NetExpr *normalize_variable_slice_base(const list<long>&indices, NetExpr*base,
|
||||||
-- pcur;
|
-- pcur;
|
||||||
}
|
}
|
||||||
|
|
||||||
long sb;
|
long sb = min(pcur->get_lsb(), pcur->get_msb());
|
||||||
if (pcur->get_msb() >= pcur->get_lsb())
|
|
||||||
sb = pcur->get_lsb();
|
|
||||||
else
|
|
||||||
sb = pcur->get_msb();
|
|
||||||
|
|
||||||
long loff;
|
long loff;
|
||||||
reg->sb_to_slice(indices, sb, loff, lwid);
|
reg->sb_to_slice(indices, sb, loff, lwid);
|
||||||
|
|
||||||
|
unsigned min_wid = base->expr_width();
|
||||||
|
if ((sb < 0) && !base->has_sign()) min_wid += 1;
|
||||||
|
if (min_wid < num_bits(pcur->get_lsb())) min_wid = pcur->get_lsb();
|
||||||
|
if (min_wid < num_bits(pcur->get_msb())) min_wid = pcur->get_msb();
|
||||||
|
base = pad_to_width(base, min_wid, *base);
|
||||||
|
if ((sb < 0) && !base->has_sign()) {
|
||||||
|
NetESelect *tmp = new NetESelect(base, 0 , min_wid);
|
||||||
|
tmp->set_line(*base);
|
||||||
|
tmp->cast_signed(true);
|
||||||
|
base = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pcur->get_msb() >= pcur->get_lsb()) {
|
||||||
|
if (pcur->get_lsb() != 0)
|
||||||
|
base = make_sub_expr(base, pcur->get_lsb());
|
||||||
base = make_mult_expr(base, lwid);
|
base = make_mult_expr(base, lwid);
|
||||||
|
min_wid = base->expr_width();
|
||||||
|
if (min_wid < num_bits(loff)) min_wid = num_bits(loff);
|
||||||
|
if (loff != 0) min_wid += 1;
|
||||||
|
base = pad_to_width(base, min_wid, *base);
|
||||||
base = make_add_expr(base, loff);
|
base = make_add_expr(base, loff);
|
||||||
|
} else {
|
||||||
|
if (pcur->get_msb() != 0)
|
||||||
|
base = make_sub_expr(base, pcur->get_msb());
|
||||||
|
base = make_mult_expr(base, lwid);
|
||||||
|
min_wid = base->expr_width();
|
||||||
|
if (min_wid < num_bits(loff)) min_wid = num_bits(loff);
|
||||||
|
if (loff != 0) min_wid += 1;
|
||||||
|
base = pad_to_width(base, min_wid, *base);
|
||||||
|
base = make_sub_expr(loff, base);
|
||||||
|
}
|
||||||
return base;
|
return base;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -802,9 +845,10 @@ NetExpr* condition_reduce(NetExpr*expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
static NetExpr* do_elab_and_eval(Design*des, NetScope*scope, PExpr*pe,
|
static NetExpr* do_elab_and_eval(Design*des, NetScope*scope, PExpr*pe,
|
||||||
int context_width, bool need_const, bool annotatable,
|
int context_width, bool need_const,
|
||||||
bool force_expand,
|
bool annotatable, bool force_expand,
|
||||||
ivl_variable_type_t cast_type)
|
ivl_variable_type_t cast_type,
|
||||||
|
bool force_unsigned)
|
||||||
{
|
{
|
||||||
PExpr::width_mode_t mode = PExpr::SIZED;
|
PExpr::width_mode_t mode = PExpr::SIZED;
|
||||||
if ((context_width == -2) && !gn_strict_expr_width_flag)
|
if ((context_width == -2) && !gn_strict_expr_width_flag)
|
||||||
|
|
@ -824,6 +868,11 @@ static NetExpr* do_elab_and_eval(Design*des, NetScope*scope, PExpr*pe,
|
||||||
if ((pe->expr_type() != IVL_VT_REAL) && (expr_width < pos_context_width))
|
if ((pe->expr_type() != IVL_VT_REAL) && (expr_width < pos_context_width))
|
||||||
expr_width = pos_context_width;
|
expr_width = pos_context_width;
|
||||||
|
|
||||||
|
// If this is the RHS of a compressed assignment, the LHS also
|
||||||
|
// affects the expression type (signed/unsigned).
|
||||||
|
if (force_unsigned)
|
||||||
|
pe->cast_signed(false);
|
||||||
|
|
||||||
if (debug_elaborate) {
|
if (debug_elaborate) {
|
||||||
cerr << pe->get_fileline() << ": elab_and_eval: test_width of "
|
cerr << pe->get_fileline() << ": elab_and_eval: test_width of "
|
||||||
<< *pe << endl;
|
<< *pe << endl;
|
||||||
|
|
@ -910,15 +959,16 @@ static NetExpr* do_elab_and_eval(Design*des, NetScope*scope, PExpr*pe,
|
||||||
|
|
||||||
NetExpr* elab_and_eval(Design*des, NetScope*scope, PExpr*pe,
|
NetExpr* elab_and_eval(Design*des, NetScope*scope, PExpr*pe,
|
||||||
int context_width, bool need_const, bool annotatable,
|
int context_width, bool need_const, bool annotatable,
|
||||||
ivl_variable_type_t cast_type)
|
ivl_variable_type_t cast_type, bool force_unsigned)
|
||||||
{
|
{
|
||||||
return do_elab_and_eval(des, scope, pe, context_width,
|
return do_elab_and_eval(des, scope, pe, context_width,
|
||||||
need_const, annotatable, false, cast_type);
|
need_const, annotatable, false,
|
||||||
|
cast_type, force_unsigned);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This variant of elab_and_eval does the expression losslessly, no
|
* This variant of elab_and_eval does the expression losslessly, no
|
||||||
* matter what the generation of verilog. This is in support of
|
* matter what the generation of Verilog. This is in support of
|
||||||
* certain special contexts, notably index expressions.
|
* certain special contexts, notably index expressions.
|
||||||
*/
|
*/
|
||||||
NetExpr* elab_and_eval_lossless(Design*des, NetScope*scope, PExpr*pe,
|
NetExpr* elab_and_eval_lossless(Design*des, NetScope*scope, PExpr*pe,
|
||||||
|
|
@ -926,7 +976,8 @@ NetExpr* elab_and_eval_lossless(Design*des, NetScope*scope, PExpr*pe,
|
||||||
ivl_variable_type_t cast_type)
|
ivl_variable_type_t cast_type)
|
||||||
{
|
{
|
||||||
return do_elab_and_eval(des, scope, pe, context_width,
|
return do_elab_and_eval(des, scope, pe, context_width,
|
||||||
need_const, annotatable, true, cast_type);
|
need_const, annotatable, true,
|
||||||
|
cast_type, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
NetExpr* elab_and_eval(Design*des, NetScope*scope, PExpr*pe,
|
NetExpr* elab_and_eval(Design*des, NetScope*scope, PExpr*pe,
|
||||||
|
|
@ -1404,7 +1455,7 @@ bool evaluate_index_prefix(Design*des, NetScope*scope,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
prefix_indices .push_back(tmp);
|
prefix_indices.push_back(tmp);
|
||||||
delete texpr;
|
delete texpr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
38
netmisc.h
38
netmisc.h
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef IVL_netmisc_H
|
#ifndef IVL_netmisc_H
|
||||||
#define IVL_netmisc_H
|
#define IVL_netmisc_H
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1999-2014 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 1999-2016 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -60,12 +60,32 @@ inline NetScope* symbol_search(const LineInfo*li,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function transforms an expression by padding the high bits
|
* This function transforms an expression by either zero or sign extending
|
||||||
* with V0 until the expression has the desired width. This may mean
|
* the high bits until the expression has the desired width. This may mean
|
||||||
* not transforming the expression at all, if it is already wide
|
* not transforming the expression at all, if it is already wide enough.
|
||||||
* enough.
|
* The extension method and the returned expression type is determined by
|
||||||
|
* signed_flag.
|
||||||
*/
|
*/
|
||||||
extern NetExpr*pad_to_width(NetExpr*expr, unsigned wid, const LineInfo&info);
|
extern NetExpr*pad_to_width(NetExpr*expr, unsigned wid, bool signed_flag,
|
||||||
|
const LineInfo&info);
|
||||||
|
/*
|
||||||
|
* This version determines the extension method from the base expression type.
|
||||||
|
*/
|
||||||
|
inline NetExpr*pad_to_width(NetExpr*expr, unsigned wid, const LineInfo&info)
|
||||||
|
{
|
||||||
|
return pad_to_width(expr, wid, expr->has_sign(), info);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function transforms an expression by either zero or sign extending
|
||||||
|
* or discarding the high bits until the expression has the desired width.
|
||||||
|
* This may mean not transforming the expression at all, if it is already
|
||||||
|
* the correct width. The extension method (if needed) and the returned
|
||||||
|
* expression type is determined by signed_flag.
|
||||||
|
*/
|
||||||
|
extern NetExpr*cast_to_width(NetExpr*expr, unsigned wid, bool signed_flag,
|
||||||
|
const LineInfo&info);
|
||||||
|
|
||||||
extern NetNet*pad_to_width(Design*des, NetNet*n, unsigned w,
|
extern NetNet*pad_to_width(Design*des, NetNet*n, unsigned w,
|
||||||
const LineInfo&info);
|
const LineInfo&info);
|
||||||
|
|
||||||
|
|
@ -258,7 +278,8 @@ extern NetExpr* elab_and_eval(Design*des, NetScope*scope,
|
||||||
PExpr*pe, int context_width,
|
PExpr*pe, int context_width,
|
||||||
bool need_const =false,
|
bool need_const =false,
|
||||||
bool annotatable =false,
|
bool annotatable =false,
|
||||||
ivl_variable_type_t cast_type =IVL_VT_NO_TYPE);
|
ivl_variable_type_t cast_type =IVL_VT_NO_TYPE,
|
||||||
|
bool force_unsigned =false);
|
||||||
|
|
||||||
extern NetExpr* elab_and_eval_lossless(Design*des, NetScope*scope,
|
extern NetExpr* elab_and_eval_lossless(Design*des, NetScope*scope,
|
||||||
PExpr*pe, int context_width,
|
PExpr*pe, int context_width,
|
||||||
|
|
@ -297,7 +318,8 @@ extern NetExpr* elaborate_rval_expr(Design*des, NetScope*scope,
|
||||||
ivl_type_t lv_net_type,
|
ivl_type_t lv_net_type,
|
||||||
ivl_variable_type_t lv_type,
|
ivl_variable_type_t lv_type,
|
||||||
unsigned lv_width, PExpr*expr,
|
unsigned lv_width, PExpr*expr,
|
||||||
bool need_const =false);
|
bool need_const =false,
|
||||||
|
bool force_unsigned =false);
|
||||||
|
|
||||||
extern bool evaluate_ranges(Design*des, NetScope*scope,
|
extern bool evaluate_ranges(Design*des, NetScope*scope,
|
||||||
std::vector<netrange_t>&llist,
|
std::vector<netrange_t>&llist,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2012-2013 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2012-2016 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -147,13 +147,12 @@ bool prefix_to_slice(const std::vector<netrange_t>&dims,
|
||||||
do {
|
do {
|
||||||
-- icur;
|
-- icur;
|
||||||
acc_wid *= pcur->width();
|
acc_wid *= pcur->width();
|
||||||
|
-- pcur;
|
||||||
if (pcur->get_msb() >= pcur->get_lsb())
|
if (pcur->get_msb() >= pcur->get_lsb())
|
||||||
acc_off += (*icur - pcur->get_lsb()) * acc_wid;
|
acc_off += (*icur - pcur->get_lsb()) * acc_wid;
|
||||||
else
|
else
|
||||||
acc_off += (pcur->get_lsb() - *icur) * acc_wid;
|
acc_off += (pcur->get_lsb() - *icur) * acc_wid;
|
||||||
|
|
||||||
-- pcur;
|
|
||||||
|
|
||||||
} while (icur != prefix.begin());
|
} while (icur != prefix.begin());
|
||||||
|
|
||||||
// Got our final offset.
|
// Got our final offset.
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1999-2011 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 1999-2016 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -24,21 +24,20 @@
|
||||||
# include "netmisc.h"
|
# include "netmisc.h"
|
||||||
|
|
||||||
|
|
||||||
/*
|
NetExpr*pad_to_width(NetExpr*expr, unsigned wid, bool signed_flag,
|
||||||
* This function transforms an expression by padding the high bits
|
const LineInfo&info)
|
||||||
* with V0 until the expression has the desired width. This may mean
|
|
||||||
* not transforming the expression at all, if it is already wide
|
|
||||||
* enough.
|
|
||||||
*/
|
|
||||||
NetExpr*pad_to_width(NetExpr*expr, unsigned wid, const LineInfo&info)
|
|
||||||
{
|
{
|
||||||
if (wid <= expr->expr_width())
|
if (wid <= expr->expr_width()) {
|
||||||
|
expr->cast_signed(signed_flag);
|
||||||
return expr;
|
return expr;
|
||||||
|
}
|
||||||
|
|
||||||
/* If the expression is a const, then replace it with a wider
|
/* If the expression is a const, then replace it with a wider
|
||||||
const. This is a more efficient result. */
|
const. This is a more efficient result. */
|
||||||
if (NetEConst*tmp = dynamic_cast<NetEConst*>(expr)) {
|
if (NetEConst*tmp = dynamic_cast<NetEConst*>(expr)) {
|
||||||
verinum oval = pad_to_width(tmp->value(), wid);
|
verinum oval = tmp->value();
|
||||||
|
oval.has_sign(signed_flag);
|
||||||
|
oval = pad_to_width(oval, wid);
|
||||||
tmp = new NetEConst(oval);
|
tmp = new NetEConst(oval);
|
||||||
tmp->set_line(info);
|
tmp->set_line(info);
|
||||||
delete expr;
|
delete expr;
|
||||||
|
|
@ -46,8 +45,30 @@ NetExpr*pad_to_width(NetExpr*expr, unsigned wid, const LineInfo&info)
|
||||||
}
|
}
|
||||||
|
|
||||||
NetESelect*tmp = new NetESelect(expr, 0, wid);
|
NetESelect*tmp = new NetESelect(expr, 0, wid);
|
||||||
|
tmp->cast_signed(signed_flag);
|
||||||
tmp->set_line(info);
|
tmp->set_line(info);
|
||||||
tmp->cast_signed(expr->has_sign());
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
NetExpr*cast_to_width(NetExpr*expr, unsigned wid, bool signed_flag,
|
||||||
|
const LineInfo&info)
|
||||||
|
{
|
||||||
|
/* If the expression is a const, then replace it with a new
|
||||||
|
const. This is a more efficient result. */
|
||||||
|
if (NetEConst*tmp = dynamic_cast<NetEConst*>(expr)) {
|
||||||
|
tmp->cast_signed(signed_flag);
|
||||||
|
if (wid != tmp->expr_width()) {
|
||||||
|
tmp = new NetEConst(verinum(tmp->value(), wid));
|
||||||
|
tmp->set_line(info);
|
||||||
|
delete expr;
|
||||||
|
}
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
NetESelect*tmp = new NetESelect(expr, 0, wid);
|
||||||
|
tmp->cast_signed(signed_flag);
|
||||||
|
tmp->set_line(info);
|
||||||
|
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
366
parse.y
366
parse.y
|
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
%{
|
%{
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1998-2015 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 1998-2016 Stephen Williams (steve@icarus.com)
|
||||||
* Copyright CERN 2012-2013 / Stephen Williams (steve@icarus.com)
|
* Copyright CERN 2012-2013 / Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
|
|
@ -65,6 +65,10 @@ static PTask* current_task = 0;
|
||||||
static PFunction* current_function = 0;
|
static PFunction* current_function = 0;
|
||||||
static stack<PBlock*> current_block_stack;
|
static stack<PBlock*> current_block_stack;
|
||||||
|
|
||||||
|
/* The variable declaration rules need to know if a lifetime has been
|
||||||
|
specified. */
|
||||||
|
static LexicalScope::lifetime_t var_lifetime;
|
||||||
|
|
||||||
static pform_name_t* pform_create_this(void)
|
static pform_name_t* pform_create_this(void)
|
||||||
{
|
{
|
||||||
name_component_t name (perm_string::literal("@"));
|
name_component_t name (perm_string::literal("@"));
|
||||||
|
|
@ -131,17 +135,17 @@ static list<named_pexpr_t>*attributes_in_context = 0;
|
||||||
static const struct str_pair_t pull_strength = { IVL_DR_PULL, IVL_DR_PULL };
|
static const struct str_pair_t pull_strength = { IVL_DR_PULL, IVL_DR_PULL };
|
||||||
static const struct str_pair_t str_strength = { IVL_DR_STRONG, IVL_DR_STRONG };
|
static const struct str_pair_t str_strength = { IVL_DR_STRONG, IVL_DR_STRONG };
|
||||||
|
|
||||||
static list<pair<perm_string,PExpr*> >* make_port_list(char*id, PExpr*expr)
|
static list<pform_port_t>* make_port_list(char*id, list<pform_range_t>*udims, PExpr*expr)
|
||||||
{
|
{
|
||||||
list<pair<perm_string,PExpr*> >*tmp = new list<pair<perm_string,PExpr*> >;
|
list<pform_port_t>*tmp = new list<pform_port_t>;
|
||||||
tmp->push_back(make_pair(lex_strings.make(id), expr));
|
tmp->push_back(pform_port_t(lex_strings.make(id), udims, expr));
|
||||||
delete[]id;
|
delete[]id;
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
static list<pair<perm_string,PExpr*> >* make_port_list(list<pair<perm_string, PExpr*> >*tmp,
|
static list<pform_port_t>* make_port_list(list<pform_port_t>*tmp,
|
||||||
char*id, PExpr*expr)
|
char*id, list<pform_range_t>*udims, PExpr*expr)
|
||||||
{
|
{
|
||||||
tmp->push_back(make_pair(lex_strings.make(id), expr));
|
tmp->push_back(pform_port_t(lex_strings.make(id), udims, expr));
|
||||||
delete[]id;
|
delete[]id;
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
@ -370,7 +374,7 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
|
||||||
char*text;
|
char*text;
|
||||||
list<perm_string>*perm_strings;
|
list<perm_string>*perm_strings;
|
||||||
|
|
||||||
list<pair<perm_string,PExpr*> >*port_list;
|
list<pform_port_t>*port_list;
|
||||||
|
|
||||||
vector<pform_tf_port_t>* tf_ports;
|
vector<pform_tf_port_t>* tf_ports;
|
||||||
|
|
||||||
|
|
@ -452,6 +456,8 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
|
||||||
|
|
||||||
PSpecPath* specpath;
|
PSpecPath* specpath;
|
||||||
list<index_component_t> *dimensions;
|
list<index_component_t> *dimensions;
|
||||||
|
|
||||||
|
LexicalScope::lifetime_t lifetime;
|
||||||
};
|
};
|
||||||
|
|
||||||
%token <text> IDENTIFIER SYSTEM_IDENTIFIER STRING TIME_LITERAL
|
%token <text> IDENTIFIER SYSTEM_IDENTIFIER STRING TIME_LITERAL
|
||||||
|
|
@ -560,7 +566,7 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
|
||||||
%type <number> number pos_neg_number
|
%type <number> number pos_neg_number
|
||||||
%type <flag> signing unsigned_signed_opt signed_unsigned_opt
|
%type <flag> signing unsigned_signed_opt signed_unsigned_opt
|
||||||
%type <flag> import_export
|
%type <flag> import_export
|
||||||
%type <flag> K_automatic_opt K_packed_opt K_reg_opt K_static_opt K_virtual_opt
|
%type <flag> K_packed_opt K_reg_opt K_static_opt K_virtual_opt
|
||||||
%type <flag> udp_reg_opt edge_operator
|
%type <flag> udp_reg_opt edge_operator
|
||||||
%type <drive> drive_strength drive_strength_opt dr_strength0 dr_strength1
|
%type <drive> drive_strength drive_strength_opt dr_strength0 dr_strength1
|
||||||
%type <letter> udp_input_sym udp_output_sym
|
%type <letter> udp_input_sym udp_output_sym
|
||||||
|
|
@ -576,7 +582,7 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
|
||||||
%type <text> register_variable net_variable event_variable endlabel_opt class_declaration_endlabel_opt
|
%type <text> register_variable net_variable event_variable endlabel_opt class_declaration_endlabel_opt
|
||||||
%type <perm_strings> register_variable_list net_variable_list event_variable_list
|
%type <perm_strings> register_variable_list net_variable_list event_variable_list
|
||||||
%type <perm_strings> list_of_identifiers loop_variables
|
%type <perm_strings> list_of_identifiers loop_variables
|
||||||
%type <port_list> list_of_port_identifiers
|
%type <port_list> list_of_port_identifiers list_of_variable_port_identifiers
|
||||||
|
|
||||||
%type <net_decl_assign> net_decl_assign net_decl_assigns
|
%type <net_decl_assign> net_decl_assign net_decl_assigns
|
||||||
|
|
||||||
|
|
@ -607,7 +613,8 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
|
||||||
%type <gates> gate_instance_list
|
%type <gates> gate_instance_list
|
||||||
|
|
||||||
%type <pform_name> hierarchy_identifier implicit_class_handle
|
%type <pform_name> hierarchy_identifier implicit_class_handle
|
||||||
%type <expr> assignment_pattern expression expr_primary expr_mintypmax
|
%type <expr> assignment_pattern expression expr_mintypmax
|
||||||
|
%type <expr> expr_primary_or_typename expr_primary
|
||||||
%type <expr> class_new dynamic_array_new
|
%type <expr> class_new dynamic_array_new
|
||||||
%type <expr> inc_or_dec_expression inside_expression lpvalue
|
%type <expr> inc_or_dec_expression inside_expression lpvalue
|
||||||
%type <expr> branch_probe_expression streaming_concatenation
|
%type <expr> branch_probe_expression streaming_concatenation
|
||||||
|
|
@ -635,7 +642,7 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
|
||||||
%type <ranges> variable_dimension
|
%type <ranges> variable_dimension
|
||||||
%type <ranges> dimensions_opt dimensions
|
%type <ranges> dimensions_opt dimensions
|
||||||
|
|
||||||
%type <nettype> net_type var_type net_type_opt
|
%type <nettype> net_type net_type_opt
|
||||||
%type <gatetype> gatetype switchtype
|
%type <gatetype> gatetype switchtype
|
||||||
%type <porttype> port_direction port_direction_opt
|
%type <porttype> port_direction port_direction_opt
|
||||||
%type <vartype> bit_logic bit_logic_opt
|
%type <vartype> bit_logic bit_logic_opt
|
||||||
|
|
@ -664,6 +671,8 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
|
||||||
%type <int_val> atom2_type
|
%type <int_val> atom2_type
|
||||||
%type <int_val> module_start module_end
|
%type <int_val> module_start module_end
|
||||||
|
|
||||||
|
%type <lifetime> lifetime lifetime_opt
|
||||||
|
|
||||||
%token K_TAND
|
%token K_TAND
|
||||||
%right K_PLUS_EQ K_MINUS_EQ K_MUL_EQ K_DIV_EQ K_MOD_EQ K_AND_EQ K_OR_EQ
|
%right K_PLUS_EQ K_MINUS_EQ K_MUL_EQ K_DIV_EQ K_MOD_EQ K_AND_EQ K_OR_EQ
|
||||||
%right K_XOR_EQ K_LS_EQ K_RS_EQ K_RSS_EQ
|
%right K_XOR_EQ K_LS_EQ K_RS_EQ K_RSS_EQ
|
||||||
|
|
@ -723,17 +732,17 @@ block_identifier_opt /* */
|
||||||
;
|
;
|
||||||
|
|
||||||
class_declaration /* IEEE1800-2005: A.1.2 */
|
class_declaration /* IEEE1800-2005: A.1.2 */
|
||||||
: K_virtual_opt K_class class_identifier class_declaration_extends_opt ';'
|
: K_virtual_opt K_class lifetime_opt class_identifier class_declaration_extends_opt ';'
|
||||||
{ pform_start_class_declaration(@2, $3, $4.type, $4.exprs); }
|
{ pform_start_class_declaration(@2, $4, $5.type, $5.exprs, $3); }
|
||||||
class_items_opt K_endclass
|
class_items_opt K_endclass
|
||||||
{ // Process a class.
|
{ // Process a class.
|
||||||
pform_end_class_declaration(@8);
|
pform_end_class_declaration(@9);
|
||||||
}
|
}
|
||||||
class_declaration_endlabel_opt
|
class_declaration_endlabel_opt
|
||||||
{ // Wrap up the class.
|
{ // Wrap up the class.
|
||||||
if ($10 && $3 && $3->name != $10) {
|
if ($11 && $4 && $4->name != $11) {
|
||||||
yyerror(@10, "error: Class end label doesn't match class name.");
|
yyerror(@11, "error: Class end label doesn't match class name.");
|
||||||
delete[]$10;
|
delete[]$11;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
@ -1193,7 +1202,7 @@ for_step /* IEEE1800-2005: A.6.8 */
|
||||||
definitions in the func_body to take on the scope of the function
|
definitions in the func_body to take on the scope of the function
|
||||||
instead of the module. */
|
instead of the module. */
|
||||||
function_declaration /* IEEE1800-2005: A.2.6 */
|
function_declaration /* IEEE1800-2005: A.2.6 */
|
||||||
: K_function K_automatic_opt data_type_or_implicit_or_void IDENTIFIER ';'
|
: K_function lifetime_opt data_type_or_implicit_or_void IDENTIFIER ';'
|
||||||
{ assert(current_function == 0);
|
{ assert(current_function == 0);
|
||||||
current_function = pform_push_function_scope(@1, $4, $2);
|
current_function = pform_push_function_scope(@1, $4, $2);
|
||||||
}
|
}
|
||||||
|
|
@ -1214,7 +1223,7 @@ function_declaration /* IEEE1800-2005: A.2.6 */
|
||||||
"function name");
|
"function name");
|
||||||
}
|
}
|
||||||
if (! gn_system_verilog()) {
|
if (! gn_system_verilog()) {
|
||||||
yyerror(@11, "error: Function end label require "
|
yyerror(@11, "error: Function end labels require "
|
||||||
"SystemVerilog.");
|
"SystemVerilog.");
|
||||||
}
|
}
|
||||||
delete[]$11;
|
delete[]$11;
|
||||||
|
|
@ -1222,7 +1231,7 @@ function_declaration /* IEEE1800-2005: A.2.6 */
|
||||||
delete[]$4;
|
delete[]$4;
|
||||||
}
|
}
|
||||||
|
|
||||||
| K_function K_automatic_opt data_type_or_implicit_or_void IDENTIFIER
|
| K_function lifetime_opt data_type_or_implicit_or_void IDENTIFIER
|
||||||
{ assert(current_function == 0);
|
{ assert(current_function == 0);
|
||||||
current_function = pform_push_function_scope(@1, $4, $2);
|
current_function = pform_push_function_scope(@1, $4, $2);
|
||||||
}
|
}
|
||||||
|
|
@ -1258,7 +1267,7 @@ function_declaration /* IEEE1800-2005: A.2.6 */
|
||||||
|
|
||||||
/* Detect and recover from some errors. */
|
/* Detect and recover from some errors. */
|
||||||
|
|
||||||
| K_function K_automatic_opt data_type_or_implicit_or_void IDENTIFIER error K_endfunction
|
| K_function lifetime_opt data_type_or_implicit_or_void IDENTIFIER error K_endfunction
|
||||||
{ /* */
|
{ /* */
|
||||||
if (current_function) {
|
if (current_function) {
|
||||||
pform_pop_scope();
|
pform_pop_scope();
|
||||||
|
|
@ -1364,6 +1373,16 @@ jump_statement /* IEEE1800-2005: A.6.5 */
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
lifetime /* IEEE1800-2005: A.2.1.3 */
|
||||||
|
: K_automatic { $$ = LexicalScope::AUTOMATIC; }
|
||||||
|
| K_static { $$ = LexicalScope::STATIC; }
|
||||||
|
;
|
||||||
|
|
||||||
|
lifetime_opt /* IEEE1800-2005: A.2.1.3 */
|
||||||
|
: lifetime { $$ = $1; }
|
||||||
|
| { $$ = LexicalScope::INHERITED; }
|
||||||
|
;
|
||||||
|
|
||||||
/* Loop statements are kinds of statements. */
|
/* Loop statements are kinds of statements. */
|
||||||
|
|
||||||
loop_statement /* IEEE1800-2005: A.6.8 */
|
loop_statement /* IEEE1800-2005: A.6.8 */
|
||||||
|
|
@ -1703,20 +1722,20 @@ open_range_list /* IEEE1800-2005 A.2.11 */
|
||||||
;
|
;
|
||||||
|
|
||||||
package_declaration /* IEEE1800-2005 A.1.2 */
|
package_declaration /* IEEE1800-2005 A.1.2 */
|
||||||
: K_package IDENTIFIER ';'
|
: K_package lifetime_opt IDENTIFIER ';'
|
||||||
{ pform_start_package_declaration(@1, $2);
|
{ pform_start_package_declaration(@1, $3, $2);
|
||||||
}
|
}
|
||||||
package_item_list_opt
|
package_item_list_opt
|
||||||
K_endpackage endlabel_opt
|
K_endpackage endlabel_opt
|
||||||
{ pform_end_package_declaration(@1);
|
{ pform_end_package_declaration(@1);
|
||||||
// If an end label is present make sure it match the package name.
|
// If an end label is present make sure it match the package name.
|
||||||
if ($7) {
|
if ($8) {
|
||||||
if (strcmp($2,$7) != 0) {
|
if (strcmp($3,$8) != 0) {
|
||||||
yyerror(@7, "error: End label doesn't match package name");
|
yyerror(@8, "error: End label doesn't match package name");
|
||||||
}
|
}
|
||||||
delete[]$7;
|
delete[]$8;
|
||||||
}
|
}
|
||||||
delete[]$2;
|
delete[]$3;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
@ -1895,7 +1914,7 @@ streaming_concatenation /* IEEE1800-2005: A.8.1 */
|
||||||
|
|
||||||
task_declaration /* IEEE1800-2005: A.2.7 */
|
task_declaration /* IEEE1800-2005: A.2.7 */
|
||||||
|
|
||||||
: K_task K_automatic_opt IDENTIFIER ';'
|
: K_task lifetime_opt IDENTIFIER ';'
|
||||||
{ assert(current_task == 0);
|
{ assert(current_task == 0);
|
||||||
current_task = pform_push_task_scope(@1, $3, $2);
|
current_task = pform_push_task_scope(@1, $3, $2);
|
||||||
}
|
}
|
||||||
|
|
@ -1908,7 +1927,7 @@ task_declaration /* IEEE1800-2005: A.2.7 */
|
||||||
pform_pop_scope();
|
pform_pop_scope();
|
||||||
current_task = 0;
|
current_task = 0;
|
||||||
if ($7 && $7->size() > 1 && !gn_system_verilog()) {
|
if ($7 && $7->size() > 1 && !gn_system_verilog()) {
|
||||||
yyerror(@7, "error: Task body with multiple statements requres SystemVerilog.");
|
yyerror(@7, "error: Task body with multiple statements requires SystemVerilog.");
|
||||||
}
|
}
|
||||||
delete $7;
|
delete $7;
|
||||||
}
|
}
|
||||||
|
|
@ -1931,7 +1950,7 @@ task_declaration /* IEEE1800-2005: A.2.7 */
|
||||||
delete[]$3;
|
delete[]$3;
|
||||||
}
|
}
|
||||||
|
|
||||||
| K_task K_automatic_opt IDENTIFIER '('
|
| K_task lifetime_opt IDENTIFIER '('
|
||||||
{ assert(current_task == 0);
|
{ assert(current_task == 0);
|
||||||
current_task = pform_push_task_scope(@1, $3, $2);
|
current_task = pform_push_task_scope(@1, $3, $2);
|
||||||
}
|
}
|
||||||
|
|
@ -1965,7 +1984,7 @@ task_declaration /* IEEE1800-2005: A.2.7 */
|
||||||
delete[]$3;
|
delete[]$3;
|
||||||
}
|
}
|
||||||
|
|
||||||
| K_task K_automatic_opt IDENTIFIER '(' ')' ';'
|
| K_task lifetime_opt IDENTIFIER '(' ')' ';'
|
||||||
{ assert(current_task == 0);
|
{ assert(current_task == 0);
|
||||||
current_task = pform_push_task_scope(@1, $3, $2);
|
current_task = pform_push_task_scope(@1, $3, $2);
|
||||||
}
|
}
|
||||||
|
|
@ -1982,7 +2001,7 @@ task_declaration /* IEEE1800-2005: A.2.7 */
|
||||||
pform_pop_scope();
|
pform_pop_scope();
|
||||||
current_task = 0;
|
current_task = 0;
|
||||||
if ($9->size() > 1 && !gn_system_verilog()) {
|
if ($9->size() > 1 && !gn_system_verilog()) {
|
||||||
yyerror(@9, "error: Task body with multiple statements requres SystemVerilog.");
|
yyerror(@9, "error: Task body with multiple statements requires SystemVerilog.");
|
||||||
}
|
}
|
||||||
delete $9;
|
delete $9;
|
||||||
}
|
}
|
||||||
|
|
@ -2005,7 +2024,7 @@ task_declaration /* IEEE1800-2005: A.2.7 */
|
||||||
delete[]$3;
|
delete[]$3;
|
||||||
}
|
}
|
||||||
|
|
||||||
| K_task K_automatic_opt IDENTIFIER error K_endtask
|
| K_task lifetime_opt IDENTIFIER error K_endtask
|
||||||
{
|
{
|
||||||
assert(current_task == 0);
|
assert(current_task == 0);
|
||||||
}
|
}
|
||||||
|
|
@ -2213,7 +2232,7 @@ variable_dimension /* IEEE1800-2005: A.2.5 */
|
||||||
}
|
}
|
||||||
| '[' expression ']'
|
| '[' expression ']'
|
||||||
{ // SystemVerilog canonical range
|
{ // SystemVerilog canonical range
|
||||||
if (generation_flag < GN_VER2005_SV) {
|
if (!gn_system_verilog()) {
|
||||||
warn_count += 1;
|
warn_count += 1;
|
||||||
cerr << @2 << ": warning: Use of SystemVerilog [size] dimension. "
|
cerr << @2 << ": warning: Use of SystemVerilog [size] dimension. "
|
||||||
<< "Use at least -g2005-sv to remove this warning." << endl;
|
<< "Use at least -g2005-sv to remove this warning." << endl;
|
||||||
|
|
@ -2243,6 +2262,19 @@ variable_dimension /* IEEE1800-2005: A.2.5 */
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
variable_lifetime
|
||||||
|
: lifetime
|
||||||
|
{ if (!gn_system_verilog()) {
|
||||||
|
yyerror(@1, "error: overriding the default variable lifetime "
|
||||||
|
"requires SystemVerilog.");
|
||||||
|
} else if ($1 != pform_peek_scope()->default_lifetime) {
|
||||||
|
yyerror(@1, "sorry: overriding the default variable lifetime "
|
||||||
|
"is not yet supported.");
|
||||||
|
}
|
||||||
|
var_lifetime = $1;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
/* Verilog-2001 supports attribute lists, which can be attached to a
|
/* Verilog-2001 supports attribute lists, which can be attached to a
|
||||||
variety of different objects. The syntax inside the (* *) is a
|
variety of different objects. The syntax inside the (* *) is a
|
||||||
comma separated list of names or names with assigned values. */
|
comma separated list of names or names with assigned values. */
|
||||||
|
|
@ -2317,10 +2349,20 @@ block_item_decl
|
||||||
{ if ($1) pform_set_data_type(@1, $1, $2, NetNet::REG, attributes_in_context);
|
{ if ($1) pform_set_data_type(@1, $1, $2, NetNet::REG, attributes_in_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
| variable_lifetime data_type register_variable_list ';'
|
||||||
|
{ if ($2) pform_set_data_type(@2, $2, $3, NetNet::REG, attributes_in_context);
|
||||||
|
var_lifetime = LexicalScope::INHERITED;
|
||||||
|
}
|
||||||
|
|
||||||
| K_reg data_type register_variable_list ';'
|
| K_reg data_type register_variable_list ';'
|
||||||
{ if ($2) pform_set_data_type(@2, $2, $3, NetNet::REG, attributes_in_context);
|
{ if ($2) pform_set_data_type(@2, $2, $3, NetNet::REG, attributes_in_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
| variable_lifetime K_reg data_type register_variable_list ';'
|
||||||
|
{ if ($3) pform_set_data_type(@3, $3, $4, NetNet::REG, attributes_in_context);
|
||||||
|
var_lifetime = LexicalScope::INHERITED;
|
||||||
|
}
|
||||||
|
|
||||||
| K_event event_variable_list ';'
|
| K_event event_variable_list ';'
|
||||||
{ if ($2) pform_make_events($2, @1.text, @1.first_line);
|
{ if ($2) pform_make_events($2, @1.text, @1.first_line);
|
||||||
}
|
}
|
||||||
|
|
@ -3033,7 +3075,7 @@ branch_probe_expression
|
||||||
;
|
;
|
||||||
|
|
||||||
expression
|
expression
|
||||||
: expr_primary
|
: expr_primary_or_typename
|
||||||
{ $$ = $1; }
|
{ $$ = $1; }
|
||||||
| inc_or_dec_expression
|
| inc_or_dec_expression
|
||||||
{ $$ = $1; }
|
{ $$ = $1; }
|
||||||
|
|
@ -3328,6 +3370,20 @@ expression_list_proper
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
expr_primary_or_typename
|
||||||
|
: expr_primary
|
||||||
|
|
||||||
|
/* There are a few special cases (notably $bits argument) where the
|
||||||
|
expression may be a type name. Let the elaborator sort this out. */
|
||||||
|
| TYPE_IDENTIFIER
|
||||||
|
{ PETypename*tmp = new PETypename($1.type);
|
||||||
|
FILE_NAME(tmp,@1);
|
||||||
|
$$ = tmp;
|
||||||
|
delete[]$1.text;
|
||||||
|
}
|
||||||
|
|
||||||
|
;
|
||||||
|
|
||||||
expr_primary
|
expr_primary
|
||||||
: number
|
: number
|
||||||
{ assert($1);
|
{ assert($1);
|
||||||
|
|
@ -3369,15 +3425,6 @@ expr_primary
|
||||||
delete[]$1;
|
delete[]$1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* There are a few special cases (notably $bits argument) where the
|
|
||||||
expression may be a type name. Let the elaborator sort this out. */
|
|
||||||
| TYPE_IDENTIFIER
|
|
||||||
{ PETypename*tmp = new PETypename($1.type);
|
|
||||||
FILE_NAME(tmp,@1);
|
|
||||||
$$ = tmp;
|
|
||||||
delete[]$1.text;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The hierarchy_identifier rule matches simple identifiers as well as
|
/* The hierarchy_identifier rule matches simple identifiers as well as
|
||||||
indexed arrays and part selects */
|
indexed arrays and part selects */
|
||||||
|
|
||||||
|
|
@ -3681,12 +3728,11 @@ expr_primary
|
||||||
|
|
||||||
/* Cast expressions are primaries */
|
/* Cast expressions are primaries */
|
||||||
|
|
||||||
| DEC_NUMBER '\'' '(' expression ')'
|
| expr_primary '\'' '(' expression ')'
|
||||||
{ PExpr*base = $4;
|
{ PExpr*base = $4;
|
||||||
if (gn_system_verilog()) {
|
if (gn_system_verilog()) {
|
||||||
PECastSize*tmp = new PECastSize($1->as_ulong(), base);
|
PECastSize*tmp = new PECastSize($1, base);
|
||||||
FILE_NAME(tmp, @1);
|
FILE_NAME(tmp, @1);
|
||||||
delete $1;
|
|
||||||
$$ = tmp;
|
$$ = tmp;
|
||||||
} else {
|
} else {
|
||||||
yyerror(@1, "error: Size cast requires SystemVerilog.");
|
yyerror(@1, "error: Size cast requires SystemVerilog.");
|
||||||
|
|
@ -4002,14 +4048,21 @@ list_of_identifiers
|
||||||
;
|
;
|
||||||
|
|
||||||
list_of_port_identifiers
|
list_of_port_identifiers
|
||||||
: IDENTIFIER
|
: IDENTIFIER dimensions_opt
|
||||||
{ $$ = make_port_list($1, 0); }
|
{ $$ = make_port_list($1, $2, 0); }
|
||||||
| IDENTIFIER '=' expression
|
| list_of_port_identifiers ',' IDENTIFIER dimensions_opt
|
||||||
{ $$ = make_port_list($1, $3); }
|
{ $$ = make_port_list($1, $3, $4, 0); }
|
||||||
| list_of_port_identifiers ',' IDENTIFIER
|
;
|
||||||
{ $$ = make_port_list($1, $3, 0); }
|
|
||||||
| list_of_port_identifiers ',' IDENTIFIER '=' expression
|
list_of_variable_port_identifiers
|
||||||
{ $$ = make_port_list($1, $3, $5); }
|
: IDENTIFIER dimensions_opt
|
||||||
|
{ $$ = make_port_list($1, $2, 0); }
|
||||||
|
| IDENTIFIER dimensions_opt '=' expression
|
||||||
|
{ $$ = make_port_list($1, $2, $4); }
|
||||||
|
| list_of_variable_port_identifiers ',' IDENTIFIER dimensions_opt
|
||||||
|
{ $$ = make_port_list($1, $3, $4, 0); }
|
||||||
|
| list_of_variable_port_identifiers ',' IDENTIFIER dimensions_opt '=' expression
|
||||||
|
{ $$ = make_port_list($1, $3, $4, $6); }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -4218,7 +4271,7 @@ port_declaration
|
||||||
port_declaration_context.port_net_type = use_type;
|
port_declaration_context.port_net_type = use_type;
|
||||||
port_declaration_context.data_type = $4;
|
port_declaration_context.data_type = $4;
|
||||||
|
|
||||||
pform_make_reginit(@5, name, $7);
|
pform_make_var_init(@5, name, $7);
|
||||||
|
|
||||||
delete[]$5;
|
delete[]$5;
|
||||||
$$ = ptmp;
|
$$ = ptmp;
|
||||||
|
|
@ -4372,13 +4425,13 @@ local_timeunit_prec_decl2
|
||||||
items, and finally an end marker. */
|
items, and finally an end marker. */
|
||||||
|
|
||||||
module
|
module
|
||||||
: attribute_list_opt module_start IDENTIFIER
|
: attribute_list_opt module_start lifetime_opt IDENTIFIER
|
||||||
{ pform_startmodule(@2, $3, $2==K_program, $2==K_interface, $1); }
|
{ pform_startmodule(@2, $4, $2==K_program, $2==K_interface, $3, $1); }
|
||||||
module_package_import_list_opt
|
module_package_import_list_opt
|
||||||
module_parameter_port_list_opt
|
module_parameter_port_list_opt
|
||||||
module_port_list_opt
|
module_port_list_opt
|
||||||
module_attribute_foreign ';'
|
module_attribute_foreign ';'
|
||||||
{ pform_module_set_ports($7); }
|
{ pform_module_set_ports($8); }
|
||||||
local_timeunit_prec_decl_opt
|
local_timeunit_prec_decl_opt
|
||||||
{ have_timeunit_decl = true; // Every thing past here is
|
{ have_timeunit_decl = true; // Every thing past here is
|
||||||
have_timeprec_decl = true; // a check!
|
have_timeprec_decl = true; // a check!
|
||||||
|
|
@ -4404,22 +4457,22 @@ module
|
||||||
}
|
}
|
||||||
// Check that program/endprogram and module/endmodule
|
// Check that program/endprogram and module/endmodule
|
||||||
// keywords match.
|
// keywords match.
|
||||||
if ($2 != $14) {
|
if ($2 != $15) {
|
||||||
switch ($2) {
|
switch ($2) {
|
||||||
case K_module:
|
case K_module:
|
||||||
yyerror(@14, "error: module not closed by endmodule.");
|
yyerror(@15, "error: module not closed by endmodule.");
|
||||||
break;
|
break;
|
||||||
case K_program:
|
case K_program:
|
||||||
yyerror(@14, "error: program not closed by endprogram.");
|
yyerror(@15, "error: program not closed by endprogram.");
|
||||||
break;
|
break;
|
||||||
case K_interface:
|
case K_interface:
|
||||||
yyerror(@14, "error: interface not closed by endinterface.");
|
yyerror(@15, "error: interface not closed by endinterface.");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pform_endmodule($3, in_celldefine, ucd);
|
pform_endmodule($4, in_celldefine, ucd);
|
||||||
have_timeunit_decl = false; // We will allow decls again.
|
have_timeunit_decl = false; // We will allow decls again.
|
||||||
have_timeprec_decl = false;
|
have_timeprec_decl = false;
|
||||||
}
|
}
|
||||||
|
|
@ -4429,19 +4482,19 @@ module
|
||||||
// endlabel_opt but still have the pform_endmodule() called
|
// endlabel_opt but still have the pform_endmodule() called
|
||||||
// early enough that the lexor can know we are outside the
|
// early enough that the lexor can know we are outside the
|
||||||
// module.
|
// module.
|
||||||
if ($16) {
|
if ($17) {
|
||||||
if (strcmp($3,$16) != 0) {
|
if (strcmp($4,$17) != 0) {
|
||||||
switch ($2) {
|
switch ($2) {
|
||||||
case K_module:
|
case K_module:
|
||||||
yyerror(@16, "error: End label doesn't match "
|
yyerror(@17, "error: End label doesn't match "
|
||||||
"module name.");
|
"module name.");
|
||||||
break;
|
break;
|
||||||
case K_program:
|
case K_program:
|
||||||
yyerror(@16, "error: End label doesn't match "
|
yyerror(@17, "error: End label doesn't match "
|
||||||
"program name.");
|
"program name.");
|
||||||
break;
|
break;
|
||||||
case K_interface:
|
case K_interface:
|
||||||
yyerror(@16, "error: End label doesn't match "
|
yyerror(@17, "error: End label doesn't match "
|
||||||
"interface name.");
|
"interface name.");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
@ -4452,9 +4505,9 @@ module
|
||||||
yyerror(@8, "error: Module end labels require "
|
yyerror(@8, "error: Module end labels require "
|
||||||
"SystemVerilog.");
|
"SystemVerilog.");
|
||||||
}
|
}
|
||||||
delete[]$16;
|
delete[]$17;
|
||||||
}
|
}
|
||||||
delete[]$3;
|
delete[]$4;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
@ -4597,58 +4650,102 @@ module_item
|
||||||
delete $4;
|
delete $4;
|
||||||
}
|
}
|
||||||
|
|
||||||
| attribute_list_opt port_direction unsigned_signed_opt dimensions_opt delay3_opt list_of_identifiers ';'
|
|
||||||
{ pform_set_port_type(@2, $6, $4, $3, $2, $1); }
|
|
||||||
|
|
||||||
/* The next two rules handle Verilog 2001 statements of the form:
|
/* The next two rules handle port declarations that include a net type, e.g.
|
||||||
input wire signed [h:l] <list>;
|
input wire signed [h:l] <list>;
|
||||||
This creates the wire and sets the port type all at once. */
|
This creates the wire and sets the port type all at once. */
|
||||||
|
|
||||||
| attribute_list_opt port_direction net_type unsigned_signed_opt dimensions_opt list_of_identifiers ';'
|
| attribute_list_opt port_direction net_type data_type_or_implicit list_of_port_identifiers ';'
|
||||||
{ pform_makewire(@2, $5, $4, $6, $3, $2, IVL_VT_NO_TYPE, $1, SR_BOTH); }
|
{ pform_module_define_port(@2, $5, $2, $3, $4, $1); }
|
||||||
|
|
||||||
| attribute_list_opt K_output var_type unsigned_signed_opt dimensions_opt list_of_port_identifiers ';'
|
| attribute_list_opt port_direction K_wreal list_of_port_identifiers ';'
|
||||||
{ list<pair<perm_string,PExpr*> >::const_iterator pp;
|
{ real_type_t*real_type = new real_type_t(real_type_t::REAL);
|
||||||
list<perm_string>*tmp = new list<perm_string>;
|
pform_module_define_port(@2, $4, $2, NetNet::WIRE, real_type, $1);
|
||||||
for (pp = $6->begin(); pp != $6->end(); ++ pp ) {
|
|
||||||
tmp->push_back((*pp).first);
|
|
||||||
}
|
|
||||||
pform_makewire(@2, $5, $4, tmp, $3, NetNet::POUTPUT,
|
|
||||||
IVL_VT_NO_TYPE, $1, SR_BOTH);
|
|
||||||
for (pp = $6->begin(); pp != $6->end(); ++ pp ) {
|
|
||||||
if ((*pp).second) {
|
|
||||||
pform_make_reginit(@2, (*pp).first, (*pp).second);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
delete $6;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
| attribute_list_opt port_direction K_wreal list_of_identifiers ';'
|
/* The next three rules handle port declarations that include a variable
|
||||||
{ pform_makewire(@2, 0, true, $4, NetNet::WIRE, $2,
|
type, e.g.
|
||||||
IVL_VT_REAL, $1, SR_BOTH);
|
output reg signed [h:l] <list>;
|
||||||
|
and also handle incomplete port declarations, e.g.
|
||||||
|
input signed [h:l] <list>;
|
||||||
|
*/
|
||||||
|
| attribute_list_opt K_inout data_type_or_implicit list_of_port_identifiers ';'
|
||||||
|
{ NetNet::Type use_type = $3 ? NetNet::IMPLICIT : NetNet::NONE;
|
||||||
|
if (vector_type_t*dtype = dynamic_cast<vector_type_t*> ($3)) {
|
||||||
|
if (dtype->implicit_flag)
|
||||||
|
use_type = NetNet::NONE;
|
||||||
|
}
|
||||||
|
if (use_type == NetNet::NONE)
|
||||||
|
pform_set_port_type(@2, $4, NetNet::PINOUT, $3, $1);
|
||||||
|
else
|
||||||
|
pform_module_define_port(@2, $4, NetNet::PINOUT, use_type, $3, $1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* var_type declaration (reg variables) cannot be input or output,
|
| attribute_list_opt K_input data_type_or_implicit list_of_port_identifiers ';'
|
||||||
because the port declaration implies an external driver, which
|
{ NetNet::Type use_type = $3 ? NetNet::IMPLICIT : NetNet::NONE;
|
||||||
cannot be attached to a reg. These rules catch that error early. */
|
if (vector_type_t*dtype = dynamic_cast<vector_type_t*> ($3)) {
|
||||||
|
if (dtype->implicit_flag)
|
||||||
| attribute_list_opt K_input var_type unsigned_signed_opt dimensions_opt list_of_identifiers ';'
|
use_type = NetNet::NONE;
|
||||||
{ pform_makewire(@2, $5, $4, $6, $3, NetNet::PINPUT,
|
}
|
||||||
IVL_VT_NO_TYPE, $1);
|
if (use_type == NetNet::NONE)
|
||||||
yyerror(@3, "error: reg variables cannot be inputs.");
|
pform_set_port_type(@2, $4, NetNet::PINPUT, $3, $1);
|
||||||
|
else
|
||||||
|
pform_module_define_port(@2, $4, NetNet::PINPUT, use_type, $3, $1);
|
||||||
}
|
}
|
||||||
|
|
||||||
| attribute_list_opt K_inout var_type unsigned_signed_opt dimensions_opt list_of_identifiers ';'
|
| attribute_list_opt K_output data_type_or_implicit list_of_variable_port_identifiers ';'
|
||||||
{ pform_makewire(@2, $5, $4, $6, $3, NetNet::PINOUT,
|
{ NetNet::Type use_type = $3 ? NetNet::IMPLICIT : NetNet::NONE;
|
||||||
IVL_VT_NO_TYPE, $1);
|
if (vector_type_t*dtype = dynamic_cast<vector_type_t*> ($3)) {
|
||||||
yyerror(@3, "error: reg variables cannot be inouts.");
|
if (dtype->implicit_flag)
|
||||||
|
use_type = NetNet::NONE;
|
||||||
|
else if (dtype->reg_flag)
|
||||||
|
use_type = NetNet::REG;
|
||||||
|
else
|
||||||
|
use_type = NetNet::IMPLICIT_REG;
|
||||||
|
|
||||||
|
// The SystemVerilog types that can show up as
|
||||||
|
// output ports are implicitly (on the inside)
|
||||||
|
// variables because "reg" is not valid syntax
|
||||||
|
// here.
|
||||||
|
} else if (dynamic_cast<atom2_type_t*> ($3)) {
|
||||||
|
use_type = NetNet::IMPLICIT_REG;
|
||||||
|
} else if (dynamic_cast<struct_type_t*> ($3)) {
|
||||||
|
use_type = NetNet::IMPLICIT_REG;
|
||||||
|
} else if (enum_type_t*etype = dynamic_cast<enum_type_t*> ($3)) {
|
||||||
|
if(etype->base_type == IVL_VT_LOGIC)
|
||||||
|
use_type = NetNet::IMPLICIT_REG;
|
||||||
|
}
|
||||||
|
if (use_type == NetNet::NONE)
|
||||||
|
pform_set_port_type(@2, $4, NetNet::POUTPUT, $3, $1);
|
||||||
|
else
|
||||||
|
pform_module_define_port(@2, $4, NetNet::POUTPUT, use_type, $3, $1);
|
||||||
}
|
}
|
||||||
|
|
||||||
| attribute_list_opt port_direction unsigned_signed_opt dimensions_opt delay3_opt error ';'
|
| attribute_list_opt port_direction net_type data_type_or_implicit error ';'
|
||||||
{ yyerror(@2, "error: Invalid variable list in port declaration.");
|
{ yyerror(@2, "error: Invalid variable list in port declaration.");
|
||||||
if ($1) delete $1;
|
if ($1) delete $1;
|
||||||
if ($4) delete $4;
|
if ($4) delete $4;
|
||||||
if ($5) delete $5;
|
yyerrok;
|
||||||
|
}
|
||||||
|
|
||||||
|
| attribute_list_opt K_inout data_type_or_implicit error ';'
|
||||||
|
{ yyerror(@2, "error: Invalid variable list in port declaration.");
|
||||||
|
if ($1) delete $1;
|
||||||
|
if ($3) delete $3;
|
||||||
|
yyerrok;
|
||||||
|
}
|
||||||
|
|
||||||
|
| attribute_list_opt K_input data_type_or_implicit error ';'
|
||||||
|
{ yyerror(@2, "error: Invalid variable list in port declaration.");
|
||||||
|
if ($1) delete $1;
|
||||||
|
if ($3) delete $3;
|
||||||
|
yyerrok;
|
||||||
|
}
|
||||||
|
|
||||||
|
| attribute_list_opt K_output data_type_or_implicit error ';'
|
||||||
|
{ yyerror(@2, "error: Invalid variable list in port declaration.");
|
||||||
|
if ($1) delete $1;
|
||||||
|
if ($3) delete $3;
|
||||||
yyerrok;
|
yyerrok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -5048,10 +5145,6 @@ net_type
|
||||||
| K_uwire { $$ = NetNet::UNRESOLVED_WIRE; }
|
| K_uwire { $$ = NetNet::UNRESOLVED_WIRE; }
|
||||||
;
|
;
|
||||||
|
|
||||||
var_type
|
|
||||||
: K_reg { $$ = NetNet::REG; }
|
|
||||||
;
|
|
||||||
|
|
||||||
param_type
|
param_type
|
||||||
: bit_logic_opt unsigned_signed_opt dimensions_opt
|
: bit_logic_opt unsigned_signed_opt dimensions_opt
|
||||||
{ param_active_range = $3;
|
{ param_active_range = $3;
|
||||||
|
|
@ -5477,11 +5570,17 @@ register_variable
|
||||||
$$ = $1;
|
$$ = $1;
|
||||||
}
|
}
|
||||||
| IDENTIFIER dimensions_opt '=' expression
|
| IDENTIFIER dimensions_opt '=' expression
|
||||||
{ perm_string name = lex_strings.make($1);
|
{ if (pform_peek_scope()->var_init_needs_explicit_lifetime()
|
||||||
|
&& (var_lifetime == LexicalScope::INHERITED)) {
|
||||||
|
cerr << @3 << ": warning: Static variable initialization requires "
|
||||||
|
"explicit lifetime in this context." << endl;
|
||||||
|
warn_count += 1;
|
||||||
|
}
|
||||||
|
perm_string name = lex_strings.make($1);
|
||||||
pform_makewire(@1, name, NetNet::REG,
|
pform_makewire(@1, name, NetNet::REG,
|
||||||
NetNet::NOT_A_PORT, IVL_VT_NO_TYPE, 0);
|
NetNet::NOT_A_PORT, IVL_VT_NO_TYPE, 0);
|
||||||
pform_set_reg_idx(name, $2);
|
pform_set_reg_idx(name, $2);
|
||||||
pform_make_reginit(@1, name, $4);
|
pform_make_var_init(@1, name, $4);
|
||||||
$$ = $1;
|
$$ = $1;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
@ -5734,7 +5833,23 @@ specify_path_identifiers
|
||||||
delete[]$1;
|
delete[]$1;
|
||||||
}
|
}
|
||||||
| IDENTIFIER '[' expr_primary ']'
|
| IDENTIFIER '[' expr_primary ']'
|
||||||
{ list<perm_string>*tmp = new list<perm_string>;
|
{ if (gn_specify_blocks_flag) {
|
||||||
|
yywarn(@4, "Bit selects are not currently supported "
|
||||||
|
"in path declarations. The declaration "
|
||||||
|
"will be applied to the whole vector.");
|
||||||
|
}
|
||||||
|
list<perm_string>*tmp = new list<perm_string>;
|
||||||
|
tmp->push_back(lex_strings.make($1));
|
||||||
|
$$ = tmp;
|
||||||
|
delete[]$1;
|
||||||
|
}
|
||||||
|
| IDENTIFIER '[' expr_primary polarity_operator expr_primary ']'
|
||||||
|
{ if (gn_specify_blocks_flag) {
|
||||||
|
yywarn(@4, "Part selects are not currently supported "
|
||||||
|
"in path declarations. The declaration "
|
||||||
|
"will be applied to the whole vector.");
|
||||||
|
}
|
||||||
|
list<perm_string>*tmp = new list<perm_string>;
|
||||||
tmp->push_back(lex_strings.make($1));
|
tmp->push_back(lex_strings.make($1));
|
||||||
$$ = tmp;
|
$$ = tmp;
|
||||||
delete[]$1;
|
delete[]$1;
|
||||||
|
|
@ -5746,7 +5861,23 @@ specify_path_identifiers
|
||||||
delete[]$3;
|
delete[]$3;
|
||||||
}
|
}
|
||||||
| specify_path_identifiers ',' IDENTIFIER '[' expr_primary ']'
|
| specify_path_identifiers ',' IDENTIFIER '[' expr_primary ']'
|
||||||
{ list<perm_string>*tmp = $1;
|
{ if (gn_specify_blocks_flag) {
|
||||||
|
yywarn(@4, "Bit selects are not currently supported "
|
||||||
|
"in path declarations. The declaration "
|
||||||
|
"will be applied to the whole vector.");
|
||||||
|
}
|
||||||
|
list<perm_string>*tmp = $1;
|
||||||
|
tmp->push_back(lex_strings.make($3));
|
||||||
|
$$ = tmp;
|
||||||
|
delete[]$3;
|
||||||
|
}
|
||||||
|
| specify_path_identifiers ',' IDENTIFIER '[' expr_primary polarity_operator expr_primary ']'
|
||||||
|
{ if (gn_specify_blocks_flag) {
|
||||||
|
yywarn(@4, "Part selects are not currently supported "
|
||||||
|
"in path declarations. The declaration "
|
||||||
|
"will be applied to the whole vector.");
|
||||||
|
}
|
||||||
|
list<perm_string>*tmp = $1;
|
||||||
tmp->push_back(lex_strings.make($3));
|
tmp->push_back(lex_strings.make($3));
|
||||||
$$ = tmp;
|
$$ = tmp;
|
||||||
delete[]$3;
|
delete[]$3;
|
||||||
|
|
@ -6777,7 +6908,6 @@ udp_primitive
|
||||||
presence is significant. This is a fairly common pattern so
|
presence is significant. This is a fairly common pattern so
|
||||||
collect those rules here. */
|
collect those rules here. */
|
||||||
|
|
||||||
K_automatic_opt: K_automatic { $$ = true; } | { $$ = false; } ;
|
|
||||||
K_packed_opt : K_packed { $$ = true; } | { $$ = false; } ;
|
K_packed_opt : K_packed { $$ = true; } | { $$ = false; } ;
|
||||||
K_reg_opt : K_reg { $$ = true; } | { $$ = false; } ;
|
K_reg_opt : K_reg { $$ = true; } | { $$ = false; } ;
|
||||||
K_static_opt : K_static { $$ = true; } | { $$ = false; } ;
|
K_static_opt : K_static { $$ = true; } | { $$ = false; } ;
|
||||||
|
|
|
||||||
226
pform.cc
226
pform.cc
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1998-2015 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 1998-2016 Stephen Williams (steve@icarus.com)
|
||||||
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
|
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
|
|
@ -312,12 +312,29 @@ static inline void FILE_NAME(LineInfo*obj, const char*file, unsigned lineno)
|
||||||
*/
|
*/
|
||||||
static LexicalScope* lexical_scope = 0;
|
static LexicalScope* lexical_scope = 0;
|
||||||
|
|
||||||
|
LexicalScope* pform_peek_scope(void)
|
||||||
|
{
|
||||||
|
assert(lexical_scope);
|
||||||
|
return lexical_scope;
|
||||||
|
}
|
||||||
|
|
||||||
void pform_pop_scope()
|
void pform_pop_scope()
|
||||||
{
|
{
|
||||||
assert(lexical_scope);
|
assert(lexical_scope);
|
||||||
lexical_scope = lexical_scope->parent_scope();
|
lexical_scope = lexical_scope->parent_scope();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static LexicalScope::lifetime_t find_lifetime(LexicalScope::lifetime_t lifetime)
|
||||||
|
{
|
||||||
|
if (lifetime != LexicalScope::INHERITED)
|
||||||
|
return lifetime;
|
||||||
|
|
||||||
|
if (lexical_scope != 0)
|
||||||
|
return lexical_scope->default_lifetime;
|
||||||
|
|
||||||
|
return LexicalScope::STATIC;
|
||||||
|
}
|
||||||
|
|
||||||
static PScopeExtra* find_nearest_scopex(LexicalScope*scope)
|
static PScopeExtra* find_nearest_scopex(LexicalScope*scope)
|
||||||
{
|
{
|
||||||
PScopeExtra*scopex = dynamic_cast<PScopeExtra*> (scope);
|
PScopeExtra*scopex = dynamic_cast<PScopeExtra*> (scope);
|
||||||
|
|
@ -328,17 +345,37 @@ static PScopeExtra* find_nearest_scopex(LexicalScope*scope)
|
||||||
return scopex;
|
return scopex;
|
||||||
}
|
}
|
||||||
|
|
||||||
LexicalScope* pform_peek_scope(void)
|
/*
|
||||||
|
* Set the local time unit/precision to the global value.
|
||||||
|
*/
|
||||||
|
static void pform_set_scope_timescale(PScope*scope, const struct vlltype&loc)
|
||||||
{
|
{
|
||||||
assert(lexical_scope);
|
scope->time_unit = pform_time_unit;
|
||||||
return lexical_scope;
|
scope->time_precision = pform_time_prec;
|
||||||
|
/* If we have a timescale file then the time information is from
|
||||||
|
* a timescale directive. */
|
||||||
|
scope->time_from_timescale = pform_timescale_file != 0;
|
||||||
|
|
||||||
|
if (warn_timescale && (lexical_scope == 0) && pform_timescale_file
|
||||||
|
&& (strcmp(pform_timescale_file, loc.text) != 0)) {
|
||||||
|
|
||||||
|
cerr << loc.get_fileline() << ": warning: "
|
||||||
|
<< "timescale for " << scope->pscope_name()
|
||||||
|
<< " inherited from another file." << endl;
|
||||||
|
cerr << pform_timescale_file << ":" << pform_timescale_line
|
||||||
|
<< ": ...: The inherited timescale is here." << endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PClass* pform_push_class_scope(const struct vlltype&loc, perm_string name)
|
PClass* pform_push_class_scope(const struct vlltype&loc, perm_string name,
|
||||||
|
LexicalScope::lifetime_t lifetime)
|
||||||
{
|
{
|
||||||
PClass*class_scope = new PClass(name, lexical_scope);
|
PClass*class_scope = new PClass(name, lexical_scope);
|
||||||
|
class_scope->default_lifetime = find_lifetime(lifetime);
|
||||||
FILE_NAME(class_scope, loc);
|
FILE_NAME(class_scope, loc);
|
||||||
|
|
||||||
|
pform_set_scope_timescale(class_scope, loc);
|
||||||
|
|
||||||
PScopeExtra*scopex = find_nearest_scopex(lexical_scope);
|
PScopeExtra*scopex = find_nearest_scopex(lexical_scope);
|
||||||
|
|
||||||
assert(!pform_cur_generate);
|
assert(!pform_cur_generate);
|
||||||
|
|
@ -364,22 +401,33 @@ PClass* pform_push_class_scope(const struct vlltype&loc, perm_string name)
|
||||||
return class_scope;
|
return class_scope;
|
||||||
}
|
}
|
||||||
|
|
||||||
PPackage* pform_push_package_scope(const struct vlltype&loc, perm_string name)
|
PPackage* pform_push_package_scope(const struct vlltype&loc, perm_string name,
|
||||||
|
LexicalScope::lifetime_t lifetime)
|
||||||
{
|
{
|
||||||
PPackage*pkg_scope = new PPackage(name, lexical_scope);
|
PPackage*pkg_scope = new PPackage(name, lexical_scope);
|
||||||
|
pkg_scope->default_lifetime = find_lifetime(lifetime);
|
||||||
FILE_NAME(pkg_scope, loc);
|
FILE_NAME(pkg_scope, loc);
|
||||||
|
|
||||||
|
pform_set_scope_timescale(pkg_scope, loc);
|
||||||
|
|
||||||
lexical_scope = pkg_scope;
|
lexical_scope = pkg_scope;
|
||||||
return pkg_scope;
|
return pkg_scope;
|
||||||
}
|
}
|
||||||
|
|
||||||
PTask* pform_push_task_scope(const struct vlltype&loc, char*name, bool is_auto)
|
PTask* pform_push_task_scope(const struct vlltype&loc, char*name,
|
||||||
|
LexicalScope::lifetime_t lifetime)
|
||||||
{
|
{
|
||||||
perm_string task_name = lex_strings.make(name);
|
perm_string task_name = lex_strings.make(name);
|
||||||
|
|
||||||
|
LexicalScope::lifetime_t default_lifetime = find_lifetime(lifetime);
|
||||||
|
bool is_auto = default_lifetime == LexicalScope::AUTOMATIC;
|
||||||
|
|
||||||
PTask*task = new PTask(task_name, lexical_scope, is_auto);
|
PTask*task = new PTask(task_name, lexical_scope, is_auto);
|
||||||
|
task->default_lifetime = default_lifetime;
|
||||||
FILE_NAME(task, loc);
|
FILE_NAME(task, loc);
|
||||||
|
|
||||||
|
pform_set_scope_timescale(task, loc);
|
||||||
|
|
||||||
PScopeExtra*scopex = find_nearest_scopex(lexical_scope);
|
PScopeExtra*scopex = find_nearest_scopex(lexical_scope);
|
||||||
if ((scopex == 0) && !gn_system_verilog()) {
|
if ((scopex == 0) && !gn_system_verilog()) {
|
||||||
cerr << task->get_fileline() << ": error: task declarations "
|
cerr << task->get_fileline() << ": error: task declarations "
|
||||||
|
|
@ -424,15 +472,21 @@ PTask* pform_push_task_scope(const struct vlltype&loc, char*name, bool is_auto)
|
||||||
}
|
}
|
||||||
|
|
||||||
PFunction* pform_push_function_scope(const struct vlltype&loc, const char*name,
|
PFunction* pform_push_function_scope(const struct vlltype&loc, const char*name,
|
||||||
bool is_auto)
|
LexicalScope::lifetime_t lifetime)
|
||||||
{
|
{
|
||||||
perm_string func_name = lex_strings.make(name);
|
perm_string func_name = lex_strings.make(name);
|
||||||
|
|
||||||
|
LexicalScope::lifetime_t default_lifetime = find_lifetime(lifetime);
|
||||||
|
bool is_auto = default_lifetime == LexicalScope::AUTOMATIC;
|
||||||
|
|
||||||
PFunction*func = new PFunction(func_name, lexical_scope, is_auto);
|
PFunction*func = new PFunction(func_name, lexical_scope, is_auto);
|
||||||
|
func->default_lifetime = default_lifetime;
|
||||||
FILE_NAME(func, loc);
|
FILE_NAME(func, loc);
|
||||||
|
|
||||||
|
pform_set_scope_timescale(func, loc);
|
||||||
|
|
||||||
PScopeExtra*scopex = find_nearest_scopex(lexical_scope);
|
PScopeExtra*scopex = find_nearest_scopex(lexical_scope);
|
||||||
if ((scopex == 0) && (generation_flag < GN_VER2005_SV)) {
|
if ((scopex == 0) && !gn_system_verilog()) {
|
||||||
cerr << func->get_fileline() << ": error: function declarations "
|
cerr << func->get_fileline() << ": error: function declarations "
|
||||||
"must be contained within a module." << endl;
|
"must be contained within a module." << endl;
|
||||||
error_count += 1;
|
error_count += 1;
|
||||||
|
|
@ -489,6 +543,7 @@ PBlock* pform_push_block_scope(char*name, PBlock::BL_TYPE bt)
|
||||||
}
|
}
|
||||||
|
|
||||||
PBlock*block = new PBlock(block_name, lexical_scope, bt);
|
PBlock*block = new PBlock(block_name, lexical_scope, bt);
|
||||||
|
block->default_lifetime = find_lifetime(LexicalScope::INHERITED);
|
||||||
lexical_scope = block;
|
lexical_scope = block;
|
||||||
|
|
||||||
return block;
|
return block;
|
||||||
|
|
@ -1041,6 +1096,9 @@ void pform_set_timeunit(const char*txt, bool in_module, bool only_check)
|
||||||
|
|
||||||
int pform_get_timeunit()
|
int pform_get_timeunit()
|
||||||
{
|
{
|
||||||
|
if (pform_cur_module.empty())
|
||||||
|
return pform_time_unit;
|
||||||
|
else
|
||||||
return pform_cur_module.front()->time_unit;
|
return pform_cur_module.front()->time_unit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1131,6 +1189,7 @@ verinum* pform_verinum_with_size(verinum*siz, verinum*val,
|
||||||
|
|
||||||
void pform_startmodule(const struct vlltype&loc, const char*name,
|
void pform_startmodule(const struct vlltype&loc, const char*name,
|
||||||
bool program_block, bool is_interface,
|
bool program_block, bool is_interface,
|
||||||
|
LexicalScope::lifetime_t lifetime,
|
||||||
list<named_pexpr_t>*attr)
|
list<named_pexpr_t>*attr)
|
||||||
{
|
{
|
||||||
if (! pform_cur_module.empty() && !gn_system_verilog()) {
|
if (! pform_cur_module.empty() && !gn_system_verilog()) {
|
||||||
|
|
@ -1139,6 +1198,12 @@ void pform_startmodule(const struct vlltype&loc, const char*name,
|
||||||
error_count += 1;
|
error_count += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (lifetime != LexicalScope::INHERITED && !gn_system_verilog()) {
|
||||||
|
cerr << loc << ": error: Default subroutine lifetimes "
|
||||||
|
"require SystemVerilog." << endl;
|
||||||
|
error_count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (gn_system_verilog() && ! pform_cur_module.empty()) {
|
if (gn_system_verilog() && ! pform_cur_module.empty()) {
|
||||||
if (pform_cur_module.front()->program_block) {
|
if (pform_cur_module.front()->program_block) {
|
||||||
cerr << loc << ": error: module, program, or interface "
|
cerr << loc << ": error: module, program, or interface "
|
||||||
|
|
@ -1158,17 +1223,14 @@ void pform_startmodule(const struct vlltype&loc, const char*name,
|
||||||
Module*cur_module = new Module(lexical_scope, lex_name);
|
Module*cur_module = new Module(lexical_scope, lex_name);
|
||||||
cur_module->program_block = program_block;
|
cur_module->program_block = program_block;
|
||||||
cur_module->is_interface = is_interface;
|
cur_module->is_interface = is_interface;
|
||||||
/* Set the local time unit/precision to the global value. */
|
cur_module->default_lifetime = find_lifetime(lifetime);
|
||||||
cur_module->time_unit = pform_time_unit;
|
|
||||||
cur_module->time_precision = pform_time_prec;
|
FILE_NAME(cur_module, loc);
|
||||||
|
|
||||||
|
pform_set_scope_timescale(cur_module, loc);
|
||||||
tu_local_flag = tu_global_flag;
|
tu_local_flag = tu_global_flag;
|
||||||
tp_local_flag = tp_global_flag;
|
tp_local_flag = tp_global_flag;
|
||||||
|
|
||||||
/* If we have a timescale file then the time information is from
|
|
||||||
* a timescale directive. */
|
|
||||||
cur_module->time_from_timescale = pform_timescale_file != 0;
|
|
||||||
|
|
||||||
FILE_NAME(cur_module, loc);
|
|
||||||
cur_module->library_flag = pform_library_flag;
|
cur_module->library_flag = pform_library_flag;
|
||||||
|
|
||||||
pform_cur_module.push_front(cur_module);
|
pform_cur_module.push_front(cur_module);
|
||||||
|
|
@ -1179,15 +1241,6 @@ void pform_startmodule(const struct vlltype&loc, const char*name,
|
||||||
zero. That's just the way it is, thanks to the standard. */
|
zero. That's just the way it is, thanks to the standard. */
|
||||||
scope_generate_counter = 1;
|
scope_generate_counter = 1;
|
||||||
|
|
||||||
if (warn_timescale && pform_timescale_file
|
|
||||||
&& (strcmp(pform_timescale_file,loc.text) != 0)) {
|
|
||||||
|
|
||||||
cerr << cur_module->get_fileline() << ": warning: "
|
|
||||||
<< "timescale for " << name
|
|
||||||
<< " inherited from another file." << endl;
|
|
||||||
cerr << pform_timescale_file << ":" << pform_timescale_line
|
|
||||||
<< ": ...: The inherited timescale is here." << endl;
|
|
||||||
}
|
|
||||||
pform_bind_attributes(cur_module->attributes, attr);
|
pform_bind_attributes(cur_module->attributes, attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1199,7 +1252,7 @@ void pform_startmodule(const struct vlltype&loc, const char*name,
|
||||||
void pform_check_timeunit_prec()
|
void pform_check_timeunit_prec()
|
||||||
{
|
{
|
||||||
assert(! pform_cur_module.empty());
|
assert(! pform_cur_module.empty());
|
||||||
if ((generation_flag & (GN_VER2005_SV | GN_VER2009 | GN_VER2012)) &&
|
if (gn_system_verilog() &&
|
||||||
(pform_cur_module.front()->time_unit < pform_cur_module.front()->time_precision)) {
|
(pform_cur_module.front()->time_unit < pform_cur_module.front()->time_precision)) {
|
||||||
VLerror("error: a timeprecision is missing or is too large!");
|
VLerror("error: a timeprecision is missing or is too large!");
|
||||||
} else assert(pform_cur_module.front()->time_unit >=
|
} else assert(pform_cur_module.front()->time_unit >=
|
||||||
|
|
@ -1905,6 +1958,7 @@ static void pform_set_net_range(perm_string name,
|
||||||
VLerror("error: name is not a valid net.");
|
VLerror("error: name is not a valid net.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this is not implicit ("implicit" meaning we don't
|
// If this is not implicit ("implicit" meaning we don't
|
||||||
// know what the type is yet) then set the type now.
|
// know what the type is yet) then set the type now.
|
||||||
if (net_type != NetNet::IMPLICIT && net_type != NetNet::NONE) {
|
if (net_type != NetNet::IMPLICIT && net_type != NetNet::NONE) {
|
||||||
|
|
@ -2248,22 +2302,29 @@ void pform_make_pgassign_list(list<PExpr*>*alist,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* this function makes the initial assignment to a register as given
|
* This function makes the initial assignment to a variable as given
|
||||||
* in the source. It handles the case where a reg variable is assigned
|
* in the source. It handles the case where a variable is assigned
|
||||||
* where it it declared:
|
* where it is declared, e.g.
|
||||||
*
|
*
|
||||||
* reg foo = <expr>;
|
* reg foo = <expr>;
|
||||||
*
|
*
|
||||||
* This is equivalent to the combination of statements:
|
* In Verilog-2001 this is only supported at the module level, and is
|
||||||
|
* equivalent to the combination of statements:
|
||||||
*
|
*
|
||||||
* reg foo;
|
* reg foo;
|
||||||
* initial foo = <expr>;
|
* initial foo = <expr>;
|
||||||
*
|
*
|
||||||
* and that is how it is parsed. This syntax is not part of the
|
* In SystemVerilog, variable initializations are allowed in any scope.
|
||||||
* IEEE1364-1995 standard, but is approved by OVI as enhancement
|
* For static variables, initializations are performed before the start
|
||||||
* BTF-B14.
|
* of simulation. For automatic variables, initializations are performed
|
||||||
|
* each time the enclosing block is entered. Here we store the variable
|
||||||
|
* assignments in the current scope, and later elaboration creates an
|
||||||
|
* initialization block that will be executed at the appropriate time.
|
||||||
|
*
|
||||||
|
* This syntax is not part of the IEEE1364-1995 standard, but is
|
||||||
|
* approved by OVI as enhancement BTF-B14.
|
||||||
*/
|
*/
|
||||||
void pform_make_reginit(const struct vlltype&li,
|
void pform_make_var_init(const struct vlltype&li,
|
||||||
perm_string name, PExpr*expr)
|
perm_string name, PExpr*expr)
|
||||||
{
|
{
|
||||||
if (! pform_at_module_level() && !gn_system_verilog()) {
|
if (! pform_at_module_level() && !gn_system_verilog()) {
|
||||||
|
|
@ -2275,7 +2336,7 @@ void pform_make_reginit(const struct vlltype&li,
|
||||||
|
|
||||||
PWire*cur = pform_get_wire_in_scope(name);
|
PWire*cur = pform_get_wire_in_scope(name);
|
||||||
if (cur == 0) {
|
if (cur == 0) {
|
||||||
VLerror(li, "internal error: reginit to non-register?");
|
VLerror(li, "internal error: var_init to non-register?");
|
||||||
delete expr;
|
delete expr;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -2284,10 +2345,8 @@ void pform_make_reginit(const struct vlltype&li,
|
||||||
FILE_NAME(lval, li);
|
FILE_NAME(lval, li);
|
||||||
PAssign*ass = new PAssign(lval, expr, true);
|
PAssign*ass = new PAssign(lval, expr, true);
|
||||||
FILE_NAME(ass, li);
|
FILE_NAME(ass, li);
|
||||||
PProcess*top = new PProcess(IVL_PR_INITIAL, ass);
|
|
||||||
FILE_NAME(top, li);
|
|
||||||
|
|
||||||
pform_put_behavior_in_scope(top);
|
lexical_scope->var_inits.push_back(ass);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -2305,7 +2364,8 @@ void pform_module_define_port(const struct vlltype&li,
|
||||||
NetNet::PortType port_kind,
|
NetNet::PortType port_kind,
|
||||||
NetNet::Type type,
|
NetNet::Type type,
|
||||||
data_type_t*vtype,
|
data_type_t*vtype,
|
||||||
list<named_pexpr_t>*attr)
|
list<named_pexpr_t>*attr,
|
||||||
|
bool keep_attr)
|
||||||
{
|
{
|
||||||
struct_type_t*struct_type = 0;
|
struct_type_t*struct_type = 0;
|
||||||
ivl_variable_type_t data_type = IVL_VT_NO_TYPE;
|
ivl_variable_type_t data_type = IVL_VT_NO_TYPE;
|
||||||
|
|
@ -2394,10 +2454,37 @@ void pform_module_define_port(const struct vlltype&li,
|
||||||
cur->set_unpacked_idx(*urange);
|
cur->set_unpacked_idx(*urange);
|
||||||
}
|
}
|
||||||
|
|
||||||
pform_bind_attributes(cur->attributes, attr);
|
pform_bind_attributes(cur->attributes, attr, keep_attr);
|
||||||
pform_put_wire_in_scope(name, cur);
|
pform_put_wire_in_scope(name, cur);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pform_module_define_port(const struct vlltype&li,
|
||||||
|
list<pform_port_t>*ports,
|
||||||
|
NetNet::PortType port_kind,
|
||||||
|
NetNet::Type type,
|
||||||
|
data_type_t*vtype,
|
||||||
|
list<named_pexpr_t>*attr)
|
||||||
|
{
|
||||||
|
for (list<pform_port_t>::iterator cur = ports->begin()
|
||||||
|
; cur != ports->end() ; ++ cur ) {
|
||||||
|
|
||||||
|
data_type_t*use_type = vtype;
|
||||||
|
if (cur->udims)
|
||||||
|
use_type = new uarray_type_t(vtype, cur->udims);
|
||||||
|
|
||||||
|
pform_module_define_port(li, cur->name, port_kind, type, use_type,
|
||||||
|
attr, true);
|
||||||
|
if (cur->udims)
|
||||||
|
delete use_type;
|
||||||
|
|
||||||
|
if (cur->expr)
|
||||||
|
pform_make_var_init(li, cur->name, cur->expr);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete ports;
|
||||||
|
delete attr;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function makes a single signal (a wire, a reg, etc) as
|
* This function makes a single signal (a wire, a reg, etc) as
|
||||||
* requested by the parser. The name is unscoped, so I attach the
|
* requested by the parser. The name is unscoped, so I attach the
|
||||||
|
|
@ -2591,7 +2678,7 @@ void pform_makewire(const struct vlltype&li,
|
||||||
NetNet::Type type,
|
NetNet::Type type,
|
||||||
data_type_t*data_type)
|
data_type_t*data_type)
|
||||||
{
|
{
|
||||||
if ((lexical_scope == 0) && (generation_flag < GN_VER2005_SV)) {
|
if ((lexical_scope == 0) && !gn_system_verilog()) {
|
||||||
VLerror(li, "error: variable declarations must be contained within a module.");
|
VLerror(li, "error: variable declarations must be contained within a module.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -2896,7 +2983,7 @@ void pform_set_parameter(const struct vlltype&loc,
|
||||||
LexicalScope::range_t*value_range)
|
LexicalScope::range_t*value_range)
|
||||||
{
|
{
|
||||||
LexicalScope*scope = lexical_scope;
|
LexicalScope*scope = lexical_scope;
|
||||||
if ((scope == 0) && (generation_flag < GN_VER2005_SV)) {
|
if ((scope == 0) && !gn_system_verilog()) {
|
||||||
VLerror(loc, "error: parameter declarations must be contained within a module.");
|
VLerror(loc, "error: parameter declarations must be contained within a module.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -2971,7 +3058,7 @@ void pform_set_localparam(const struct vlltype&loc,
|
||||||
bool signed_flag, list<pform_range_t>*range, PExpr*expr)
|
bool signed_flag, list<pform_range_t>*range, PExpr*expr)
|
||||||
{
|
{
|
||||||
LexicalScope*scope = lexical_scope;
|
LexicalScope*scope = lexical_scope;
|
||||||
if ((scope == 0) && (generation_flag < GN_VER2005_SV)) {
|
if ((scope == 0) && !gn_system_verilog()) {
|
||||||
VLerror(loc, "error: localparam declarations must be contained within a module.");
|
VLerror(loc, "error: localparam declarations must be contained within a module.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -3200,24 +3287,53 @@ static void pform_set_port_type(perm_string name, NetNet::PortType pt,
|
||||||
}
|
}
|
||||||
|
|
||||||
void pform_set_port_type(const struct vlltype&li,
|
void pform_set_port_type(const struct vlltype&li,
|
||||||
list<perm_string>*names,
|
list<pform_port_t>*ports,
|
||||||
list<pform_range_t>*range,
|
|
||||||
bool signed_flag,
|
|
||||||
NetNet::PortType pt,
|
NetNet::PortType pt,
|
||||||
|
data_type_t*dt,
|
||||||
list<named_pexpr_t>*attr)
|
list<named_pexpr_t>*attr)
|
||||||
{
|
{
|
||||||
assert(pt != NetNet::PIMPLICIT && pt != NetNet::NOT_A_PORT);
|
assert(pt != NetNet::PIMPLICIT && pt != NetNet::NOT_A_PORT);
|
||||||
|
|
||||||
for (list<perm_string>::iterator cur = names->begin()
|
list<pform_range_t>*range = 0;
|
||||||
; cur != names->end() ; ++ cur ) {
|
bool signed_flag = false;
|
||||||
perm_string txt = *cur;
|
if (vector_type_t*vt = dynamic_cast<vector_type_t*> (dt)) {
|
||||||
pform_set_port_type(txt, pt, li.text, li.first_line);
|
assert(vt->implicit_flag);
|
||||||
pform_set_net_range(txt, NetNet::NONE, range, signed_flag, IVL_VT_NO_TYPE,
|
range = vt->pdims.get();
|
||||||
SR_PORT, attr);
|
signed_flag = vt->signed_flag;
|
||||||
|
} else {
|
||||||
|
assert(dt == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
delete names;
|
bool have_init_expr = false;
|
||||||
delete range;
|
for (list<pform_port_t>::iterator cur = ports->begin()
|
||||||
|
; cur != ports->end() ; ++ cur ) {
|
||||||
|
|
||||||
|
pform_set_port_type(cur->name, pt, li.text, li.first_line);
|
||||||
|
pform_set_net_range(cur->name, NetNet::NONE, range, signed_flag,
|
||||||
|
IVL_VT_NO_TYPE, SR_PORT, attr);
|
||||||
|
if (cur->udims) {
|
||||||
|
cerr << li.text << ":" << li.first_line << ": warning: "
|
||||||
|
<< "Array dimensions in incomplete port declarations "
|
||||||
|
<< "are currently ignored." << endl;
|
||||||
|
cerr << li.text << ":" << li.first_line << ": : "
|
||||||
|
<< "The dimensions specified in the net or variable "
|
||||||
|
<< "declaration will be used." << endl;
|
||||||
|
delete cur->udims;
|
||||||
|
}
|
||||||
|
if (cur->expr) {
|
||||||
|
have_init_expr = true;
|
||||||
|
delete cur->expr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (have_init_expr) {
|
||||||
|
cerr << li.text << ":" << li.first_line << ": error: "
|
||||||
|
<< "Incomplete port declarations cannot be initialized."
|
||||||
|
<< endl;
|
||||||
|
error_count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete ports;
|
||||||
|
delete dt;
|
||||||
delete attr;
|
delete attr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
51
pform.h
51
pform.h
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef IVL_pform_H
|
#ifndef IVL_pform_H
|
||||||
#define IVL_pform_H
|
#define IVL_pform_H
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1998-2015 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 1998-2016 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -163,18 +163,26 @@ extern PWire* pform_get_make_wire_in_scope(perm_string name, NetNet::Type net_ty
|
||||||
*/
|
*/
|
||||||
extern void pform_startmodule(const struct vlltype&loc, const char*name,
|
extern void pform_startmodule(const struct vlltype&loc, const char*name,
|
||||||
bool program_block, bool is_interface,
|
bool program_block, bool is_interface,
|
||||||
|
LexicalScope::lifetime_t lifetime,
|
||||||
list<named_pexpr_t>*attr);
|
list<named_pexpr_t>*attr);
|
||||||
extern void pform_check_timeunit_prec();
|
extern void pform_check_timeunit_prec();
|
||||||
extern void pform_module_set_ports(vector<Module::port_t*>*);
|
extern void pform_module_set_ports(vector<Module::port_t*>*);
|
||||||
|
|
||||||
/* This function is used to support the port definition in a
|
/* These functions are used when we have a complete port definition, either
|
||||||
port_definition_list. In this case, we have everything needed to
|
in an ansi style or non-ansi style declaration. In this case, we have
|
||||||
define the port, all in one place. */
|
everything needed to define the port, all in one place. */
|
||||||
extern void pform_module_define_port(const struct vlltype&li,
|
extern void pform_module_define_port(const struct vlltype&li,
|
||||||
perm_string name,
|
perm_string name,
|
||||||
NetNet::PortType,
|
NetNet::PortType,
|
||||||
NetNet::Type type,
|
NetNet::Type type,
|
||||||
data_type_t*vtype,
|
data_type_t*vtype,
|
||||||
|
list<named_pexpr_t>*attr,
|
||||||
|
bool keep_attr =false);
|
||||||
|
extern void pform_module_define_port(const struct vlltype&li,
|
||||||
|
list<pform_port_t>*ports,
|
||||||
|
NetNet::PortType,
|
||||||
|
NetNet::Type type,
|
||||||
|
data_type_t*vtype,
|
||||||
list<named_pexpr_t>*attr);
|
list<named_pexpr_t>*attr);
|
||||||
|
|
||||||
extern Module::port_t* pform_module_port_reference(perm_string name,
|
extern Module::port_t* pform_module_port_reference(perm_string name,
|
||||||
|
|
@ -186,7 +194,8 @@ extern void pform_endmodule(const char*, bool inside_celldefine,
|
||||||
extern void pform_start_class_declaration(const struct vlltype&loc,
|
extern void pform_start_class_declaration(const struct vlltype&loc,
|
||||||
class_type_t*type,
|
class_type_t*type,
|
||||||
data_type_t*base_type,
|
data_type_t*base_type,
|
||||||
std::list<PExpr*>*base_exprs);
|
std::list<PExpr*>*base_exprs,
|
||||||
|
LexicalScope::lifetime_t lifetime);
|
||||||
extern void pform_class_property(const struct vlltype&loc,
|
extern void pform_class_property(const struct vlltype&loc,
|
||||||
property_qualifier_t pq,
|
property_qualifier_t pq,
|
||||||
data_type_t*data_type,
|
data_type_t*data_type,
|
||||||
|
|
@ -211,7 +220,8 @@ extern void pform_make_udp(perm_string name,
|
||||||
* Package related functions.
|
* Package related functions.
|
||||||
*/
|
*/
|
||||||
extern void pform_start_package_declaration(const struct vlltype&loc,
|
extern void pform_start_package_declaration(const struct vlltype&loc,
|
||||||
const char*type);
|
const char*type,
|
||||||
|
LexicalScope::lifetime_t lifetime);
|
||||||
extern void pform_end_package_declaration(const struct vlltype&loc);
|
extern void pform_end_package_declaration(const struct vlltype&loc);
|
||||||
extern void pform_package_import(const struct vlltype&loc,
|
extern void pform_package_import(const struct vlltype&loc,
|
||||||
PPackage*pkg, const char*ident);
|
PPackage*pkg, const char*ident);
|
||||||
|
|
@ -246,13 +256,20 @@ extern void pform_pop_scope();
|
||||||
*/
|
*/
|
||||||
extern LexicalScope* pform_peek_scope();
|
extern LexicalScope* pform_peek_scope();
|
||||||
|
|
||||||
extern PClass* pform_push_class_scope(const struct vlltype&loc, perm_string name);
|
extern PClass* pform_push_class_scope(const struct vlltype&loc, perm_string name,
|
||||||
|
LexicalScope::lifetime_t lifetime);
|
||||||
|
|
||||||
extern PFunction*pform_push_constructor_scope(const struct vlltype&loc);
|
extern PFunction*pform_push_constructor_scope(const struct vlltype&loc);
|
||||||
extern PPackage* pform_push_package_scope(const struct vlltype&loc, perm_string name);
|
|
||||||
|
extern PPackage* pform_push_package_scope(const struct vlltype&loc, perm_string name,
|
||||||
|
LexicalScope::lifetime_t lifetime);
|
||||||
|
|
||||||
extern PTask*pform_push_task_scope(const struct vlltype&loc, char*name,
|
extern PTask*pform_push_task_scope(const struct vlltype&loc, char*name,
|
||||||
bool is_auto);
|
LexicalScope::lifetime_t lifetime);
|
||||||
|
|
||||||
extern PFunction*pform_push_function_scope(const struct vlltype&loc, const char*name,
|
extern PFunction*pform_push_function_scope(const struct vlltype&loc, const char*name,
|
||||||
bool is_auto);
|
LexicalScope::lifetime_t lifetime);
|
||||||
|
|
||||||
extern PBlock*pform_push_block_scope(char*name, PBlock::BL_TYPE tt);
|
extern PBlock*pform_push_block_scope(char*name, PBlock::BL_TYPE tt);
|
||||||
|
|
||||||
extern void pform_put_behavior_in_scope(AProcess*proc);
|
extern void pform_put_behavior_in_scope(AProcess*proc);
|
||||||
|
|
@ -351,17 +368,17 @@ extern void pform_makewire(const struct vlltype&li,
|
||||||
list<perm_string>*names,
|
list<perm_string>*names,
|
||||||
list<named_pexpr_t>*attr);
|
list<named_pexpr_t>*attr);
|
||||||
|
|
||||||
extern void pform_make_reginit(const struct vlltype&li,
|
extern void pform_make_var_init(const struct vlltype&li,
|
||||||
perm_string name, PExpr*expr);
|
perm_string name, PExpr*expr);
|
||||||
|
|
||||||
/* Look up the names of the wires, and set the port type,
|
/* This function is used when we have an incomplete port definition in
|
||||||
i.e. input, output or inout. If the wire does not exist, create
|
a non-ansi style declaration. Look up the names of the wires, and set
|
||||||
it. The second form takes a single name. */
|
the port type, i.e. input, output or inout, and, if specified, the
|
||||||
|
range and signedness. If the wire does not exist, create it. */
|
||||||
extern void pform_set_port_type(const struct vlltype&li,
|
extern void pform_set_port_type(const struct vlltype&li,
|
||||||
list<perm_string>*names,
|
list<pform_port_t>*ports,
|
||||||
list<pform_range_t>*range,
|
|
||||||
bool signed_flag,
|
|
||||||
NetNet::PortType,
|
NetNet::PortType,
|
||||||
|
data_type_t*dt,
|
||||||
list<named_pexpr_t>*attr);
|
list<named_pexpr_t>*attr);
|
||||||
|
|
||||||
extern void pform_set_reg_idx(perm_string name,
|
extern void pform_set_reg_idx(perm_string name,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1998-2014 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 1998-2016 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -318,7 +318,7 @@ void PECallFunction::dump(ostream &out) const
|
||||||
|
|
||||||
void PECastSize::dump(ostream &out) const
|
void PECastSize::dump(ostream &out) const
|
||||||
{
|
{
|
||||||
out << size_ << "'(";
|
out << *size_ << "'(";
|
||||||
base_->dump(out);
|
base_->dump(out);
|
||||||
out << ")";
|
out << ")";
|
||||||
}
|
}
|
||||||
|
|
@ -789,6 +789,8 @@ void PBlock::dump(ostream&out, unsigned ind) const
|
||||||
dump_events_(out, ind+2);
|
dump_events_(out, ind+2);
|
||||||
|
|
||||||
dump_wires_(out, ind+2);
|
dump_wires_(out, ind+2);
|
||||||
|
|
||||||
|
dump_var_inits_(out, ind+2);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned idx = 0 ; idx < list_.size() ; idx += 1) {
|
for (unsigned idx = 0 ; idx < list_.size() ; idx += 1) {
|
||||||
|
|
@ -1030,6 +1032,8 @@ void PFunction::dump(ostream&out, unsigned ind) const
|
||||||
|
|
||||||
dump_wires_(out, ind+2);
|
dump_wires_(out, ind+2);
|
||||||
|
|
||||||
|
dump_var_inits_(out, ind+2);
|
||||||
|
|
||||||
if (statement_)
|
if (statement_)
|
||||||
statement_->dump(out, ind+2);
|
statement_->dump(out, ind+2);
|
||||||
else
|
else
|
||||||
|
|
@ -1072,6 +1076,8 @@ void PTask::dump(ostream&out, unsigned ind) const
|
||||||
|
|
||||||
dump_wires_(out, ind+2);
|
dump_wires_(out, ind+2);
|
||||||
|
|
||||||
|
dump_var_inits_(out, ind+2);
|
||||||
|
|
||||||
if (statement_)
|
if (statement_)
|
||||||
statement_->dump(out, ind+2);
|
statement_->dump(out, ind+2);
|
||||||
else
|
else
|
||||||
|
|
@ -1269,6 +1275,8 @@ void PGenerate::dump(ostream&out, unsigned indent) const
|
||||||
(*idx)->dump(out, indent+2);
|
(*idx)->dump(out, indent+2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dump_var_inits_(out, indent+2);
|
||||||
|
|
||||||
for (list<PProcess*>::const_iterator idx = behaviors.begin()
|
for (list<PProcess*>::const_iterator idx = behaviors.begin()
|
||||||
; idx != behaviors.end() ; ++ idx ) {
|
; idx != behaviors.end() ; ++ idx ) {
|
||||||
(*idx)->dump(out, indent+2);
|
(*idx)->dump(out, indent+2);
|
||||||
|
|
@ -1408,6 +1416,14 @@ void LexicalScope::dump_wires_(ostream&out, unsigned indent) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LexicalScope::dump_var_inits_(ostream&out, unsigned indent) const
|
||||||
|
{
|
||||||
|
// Iterate through and display all the register initializations.
|
||||||
|
for (unsigned idx = 0; idx < var_inits.size(); idx += 1) {
|
||||||
|
var_inits[idx]->dump(out, indent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void PScopeExtra::dump_classes_(ostream&out, unsigned indent) const
|
void PScopeExtra::dump_classes_(ostream&out, unsigned indent) const
|
||||||
{
|
{
|
||||||
// Dump the task definitions.
|
// Dump the task definitions.
|
||||||
|
|
@ -1564,6 +1580,7 @@ void Module::dump(ostream&out) const
|
||||||
(*gate)->dump(out);
|
(*gate)->dump(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dump_var_inits_(out, 4);
|
||||||
|
|
||||||
for (list<PProcess*>::const_iterator behav = behaviors.begin()
|
for (list<PProcess*>::const_iterator behav = behaviors.begin()
|
||||||
; behav != behaviors.end() ; ++ behav ) {
|
; behav != behaviors.end() ; ++ behav ) {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2012 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2012-2016 Stephen Williams (steve@icarus.com)
|
||||||
* Copyright CERN 2013 Stephen Williams (steve@icarus.com)
|
* Copyright CERN 2013 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
|
|
@ -35,12 +35,13 @@ map<perm_string,PPackage*> pform_packages;
|
||||||
|
|
||||||
static PPackage*pform_cur_package = 0;
|
static PPackage*pform_cur_package = 0;
|
||||||
|
|
||||||
void pform_start_package_declaration(const struct vlltype&loc, const char*name)
|
void pform_start_package_declaration(const struct vlltype&loc, const char*name,
|
||||||
|
LexicalScope::lifetime_t lifetime)
|
||||||
{
|
{
|
||||||
ivl_assert(loc, pform_cur_package == 0);
|
ivl_assert(loc, pform_cur_package == 0);
|
||||||
|
|
||||||
perm_string use_name = lex_strings.make(name);
|
perm_string use_name = lex_strings.make(name);
|
||||||
PPackage*pkg_scope = pform_push_package_scope(loc, use_name);
|
PPackage*pkg_scope = pform_push_package_scope(loc, use_name, lifetime);
|
||||||
FILE_NAME(pkg_scope, loc);
|
FILE_NAME(pkg_scope, loc);
|
||||||
pform_cur_package = pkg_scope;
|
pform_cur_package = pkg_scope;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2012-2014 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2012-2016 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -36,9 +36,13 @@ static PClass*pform_cur_class = 0;
|
||||||
* if present, are the "exprs" that would be passed to a chained
|
* if present, are the "exprs" that would be passed to a chained
|
||||||
* constructor.
|
* constructor.
|
||||||
*/
|
*/
|
||||||
void pform_start_class_declaration(const struct vlltype&loc, class_type_t*type, data_type_t*base_type, list<PExpr*>*base_exprs)
|
void pform_start_class_declaration(const struct vlltype&loc,
|
||||||
|
class_type_t*type,
|
||||||
|
data_type_t*base_type,
|
||||||
|
list<PExpr*>*base_exprs,
|
||||||
|
LexicalScope::lifetime_t lifetime)
|
||||||
{
|
{
|
||||||
PClass*class_scope = pform_push_class_scope(loc, type->name);
|
PClass*class_scope = pform_push_class_scope(loc, type->name, lifetime);
|
||||||
class_scope->type = type;
|
class_scope->type = type;
|
||||||
assert(pform_cur_class == 0);
|
assert(pform_cur_class == 0);
|
||||||
pform_cur_class = class_scope;
|
pform_cur_class = class_scope;
|
||||||
|
|
@ -75,6 +79,7 @@ void pform_class_property(const struct vlltype&loc,
|
||||||
if (! curp->index.empty()) {
|
if (! curp->index.empty()) {
|
||||||
list<pform_range_t>*pd = new list<pform_range_t> (curp->index);
|
list<pform_range_t>*pd = new list<pform_range_t> (curp->index);
|
||||||
use_type = new uarray_type_t(use_type, pd);
|
use_type = new uarray_type_t(use_type, pd);
|
||||||
|
FILE_NAME(use_type, loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
pform_cur_class->type->properties[curp->name]
|
pform_cur_class->type->properties[curp->name]
|
||||||
|
|
@ -127,7 +132,7 @@ void pform_set_constructor_return(PFunction*net)
|
||||||
PFunction*pform_push_constructor_scope(const struct vlltype&loc)
|
PFunction*pform_push_constructor_scope(const struct vlltype&loc)
|
||||||
{
|
{
|
||||||
assert(pform_cur_class);
|
assert(pform_cur_class);
|
||||||
PFunction*func = pform_push_function_scope(loc, "new", true);
|
PFunction*func = pform_push_function_scope(loc, "new", LexicalScope::AUTOMATIC);
|
||||||
return func;
|
return func;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -138,7 +143,7 @@ void pform_end_class_declaration(const struct vlltype&loc)
|
||||||
// If there were initializer statements, then collect them
|
// If there were initializer statements, then collect them
|
||||||
// into an implicit constructor function.
|
// into an implicit constructor function.
|
||||||
if (! pform_cur_class->type->initialize.empty()) {
|
if (! pform_cur_class->type->initialize.empty()) {
|
||||||
PFunction*func = pform_push_function_scope(loc, "new@", true);
|
PFunction*func = pform_push_function_scope(loc, "new@", LexicalScope::AUTOMATIC);
|
||||||
func->set_ports(0);
|
func->set_ports(0);
|
||||||
pform_set_constructor_return(func);
|
pform_set_constructor_return(func);
|
||||||
pform_set_this_class(loc, func);
|
pform_set_this_class(loc, func);
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef IVL_pform_types_H
|
#ifndef IVL_pform_types_H
|
||||||
#define IVL_pform_types_H
|
#define IVL_pform_types_H
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007-2014 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2007-2016 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -72,6 +72,21 @@ typedef named<PExpr*> named_pexpr_t;
|
||||||
*/
|
*/
|
||||||
typedef std::pair<PExpr*,PExpr*> pform_range_t;
|
typedef std::pair<PExpr*,PExpr*> pform_range_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The pform_port_t holds the name and optional unpacked dimensions
|
||||||
|
* and initialization expression for a single port in a list of port
|
||||||
|
* declarations.
|
||||||
|
*/
|
||||||
|
struct pform_port_t {
|
||||||
|
pform_port_t(perm_string n, list<pform_range_t>*ud, PExpr*e)
|
||||||
|
: name(n), udims(ud), expr(e) { }
|
||||||
|
~pform_port_t() { }
|
||||||
|
|
||||||
|
perm_string name;
|
||||||
|
list<pform_range_t>*udims;
|
||||||
|
PExpr*expr;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Semantic NOTES:
|
* Semantic NOTES:
|
||||||
* - The SEL_BIT is a single expression. This might me a bit select
|
* - The SEL_BIT is a single expression. This might me a bit select
|
||||||
|
|
|
||||||
|
|
@ -565,7 +565,7 @@ bool NetCase::synth_async(Design*des, NetScope*scope,
|
||||||
|
|
||||||
// The minimum selector width is the number of inputs that
|
// The minimum selector width is the number of inputs that
|
||||||
// are selected, rounded up to the nearest power of 2.
|
// are selected, rounded up to the nearest power of 2.
|
||||||
unsigned sel_need = ceil(log2(max_guard_value + 1));
|
unsigned sel_need = max(ceil(log2(max_guard_value + 1)), 1.0);
|
||||||
|
|
||||||
// If the sel_width can select more than just the explicit
|
// If the sel_width can select more than just the explicit
|
||||||
// guard values, and there is a default statement, then adjust
|
// guard values, and there is a default statement, then adjust
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2011-2014 Cary R. (cygcary@yahoo.com)
|
* Copyright (C) 2011-2016 Cary R. (cygcary@yahoo.com)
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
|
@ -747,7 +747,9 @@ void emit_name_of_nexus(ivl_scope_t scope, ivl_nexus_t nex, unsigned allow_UD)
|
||||||
* This function traverses the scope tree looking for the enclosing module
|
* This function traverses the scope tree looking for the enclosing module
|
||||||
* scope. When it is found the module scope is returned. As far as this
|
* scope. When it is found the module scope is returned. As far as this
|
||||||
* translation is concerned a package is a special form of a module
|
* translation is concerned a package is a special form of a module
|
||||||
* definition and a class is also a top level scope.
|
* definition and a class is also a top level scope. In SystemVerilog,
|
||||||
|
* tasks and functions can also be top level scopes - we create a wrapper
|
||||||
|
* module for these later.
|
||||||
*/
|
*/
|
||||||
ivl_scope_t get_module_scope(ivl_scope_t scope)
|
ivl_scope_t get_module_scope(ivl_scope_t scope)
|
||||||
{
|
{
|
||||||
|
|
@ -756,6 +758,12 @@ ivl_scope_t get_module_scope(ivl_scope_t scope)
|
||||||
(ivl_scope_type(scope) != IVL_SCT_PACKAGE) &&
|
(ivl_scope_type(scope) != IVL_SCT_PACKAGE) &&
|
||||||
(ivl_scope_type(scope) != IVL_SCT_CLASS)) {
|
(ivl_scope_type(scope) != IVL_SCT_CLASS)) {
|
||||||
ivl_scope_t pscope = ivl_scope_parent(scope);
|
ivl_scope_t pscope = ivl_scope_parent(scope);
|
||||||
|
if (pscope == 0) {
|
||||||
|
if (ivl_scope_type(scope) == IVL_SCT_TASK)
|
||||||
|
break;
|
||||||
|
if (ivl_scope_type(scope) == IVL_SCT_FUNCTION)
|
||||||
|
break;
|
||||||
|
}
|
||||||
assert(pscope);
|
assert(pscope);
|
||||||
scope = pscope;
|
scope = pscope;
|
||||||
}
|
}
|
||||||
|
|
@ -872,7 +880,8 @@ void emit_scope_path(ivl_scope_t scope, ivl_scope_t call_scope)
|
||||||
|
|
||||||
/* Check to see if this is a root scope task or function. */
|
/* Check to see if this is a root scope task or function. */
|
||||||
if (ivl_scope_parent(call_scope) == 0) {
|
if (ivl_scope_parent(call_scope) == 0) {
|
||||||
fprintf(vlog_out, "ivl_root_scope.");
|
fprintf(vlog_out, "ivl_root_scope_%s.",
|
||||||
|
ivl_scope_basename(call_scope));
|
||||||
mod_scope = 0;
|
mod_scope = 0;
|
||||||
call_mod_scope = 0;
|
call_mod_scope = 0;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -938,3 +947,30 @@ void get_sig_msb_lsb(ivl_signal_t sig, int *msb, int *lsb)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char*get_time_const(int time_value)
|
||||||
|
{
|
||||||
|
switch (time_value) {
|
||||||
|
case 2: return "100s";
|
||||||
|
case 1: return "10s";
|
||||||
|
case 0: return "1s";
|
||||||
|
case -1: return "100ms";
|
||||||
|
case -2: return "10ms";
|
||||||
|
case -3: return "1ms";
|
||||||
|
case -4: return "100us";
|
||||||
|
case -5: return "10us";
|
||||||
|
case -6: return "1us";
|
||||||
|
case -7: return "100ns";
|
||||||
|
case -8: return "10ns";
|
||||||
|
case -9: return "1ns";
|
||||||
|
case -10: return "100ps";
|
||||||
|
case -11: return "10ps";
|
||||||
|
case -12: return "1ps";
|
||||||
|
case -13: return "100fs";
|
||||||
|
case -14: return "10fs";
|
||||||
|
case -15: return "1fs";
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "Invalid time constant value %d.\n", time_value);
|
||||||
|
return "N/A";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2010-2015 Cary R. (cygcary@yahoo.com)
|
* Copyright (C) 2010-2016 Cary R. (cygcary@yahoo.com)
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
|
@ -24,33 +24,6 @@
|
||||||
|
|
||||||
const char *func_rtn_name = 0;
|
const char *func_rtn_name = 0;
|
||||||
|
|
||||||
static const char*get_time_const(int time_value)
|
|
||||||
{
|
|
||||||
switch (time_value) {
|
|
||||||
case 2: return "100s";
|
|
||||||
case 1: return "10s";
|
|
||||||
case 0: return "1s";
|
|
||||||
case -1: return "100ms";
|
|
||||||
case -2: return "10ms";
|
|
||||||
case -3: return "1ms";
|
|
||||||
case -4: return "100us";
|
|
||||||
case -5: return "10us";
|
|
||||||
case -6: return "1us";
|
|
||||||
case -7: return "100ns";
|
|
||||||
case -8: return "10ns";
|
|
||||||
case -9: return "1ns";
|
|
||||||
case -10: return "100ps";
|
|
||||||
case -11: return "10ps";
|
|
||||||
case -12: return "1ps";
|
|
||||||
case -13: return "100fs";
|
|
||||||
case -14: return "10fs";
|
|
||||||
case -15: return "1fs";
|
|
||||||
default:
|
|
||||||
fprintf(stderr, "Invalid time constant value %d.\n", time_value);
|
|
||||||
return "N/A";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void emit_func_return(ivl_signal_t sig)
|
static void emit_func_return(ivl_signal_t sig)
|
||||||
{
|
{
|
||||||
if (ivl_signal_dimensions(sig) > 0) {
|
if (ivl_signal_dimensions(sig) > 0) {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2010-2013 Cary R. (cygcary@yahoo.com)
|
* Copyright (C) 2010-2016 Cary R. (cygcary@yahoo.com)
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
|
@ -60,7 +60,6 @@ int target_design(ivl_design_t des)
|
||||||
{
|
{
|
||||||
ivl_scope_t *roots;
|
ivl_scope_t *roots;
|
||||||
unsigned nroots, idx;
|
unsigned nroots, idx;
|
||||||
unsigned has_root_scope = 0;
|
|
||||||
const char*path = ivl_design_flag(des, "-o");
|
const char*path = ivl_design_flag(des, "-o");
|
||||||
/* Set the indent spacing with the -pspacing flag passed to iverilog
|
/* Set the indent spacing with the -pspacing flag passed to iverilog
|
||||||
* (e.g. -pspacing=4). The default is 2 spaces. */
|
* (e.g. -pspacing=4). The default is 2 spaces. */
|
||||||
|
|
@ -190,23 +189,27 @@ int target_design(ivl_design_t des)
|
||||||
switch(ivl_scope_type(roots[idx])) {
|
switch(ivl_scope_type(roots[idx])) {
|
||||||
case IVL_SCT_FUNCTION:
|
case IVL_SCT_FUNCTION:
|
||||||
case IVL_SCT_TASK:
|
case IVL_SCT_TASK:
|
||||||
if (! has_root_scope) {
|
/* Create a separate module for each task/function.
|
||||||
fprintf(vlog_out, "module ivl_root_scope;\n");
|
This allows us to handle different timescales. */
|
||||||
|
fprintf(vlog_out, "\n`timescale %s/%s\n",
|
||||||
|
get_time_const(ivl_scope_time_units(roots[idx])),
|
||||||
|
get_time_const(ivl_scope_time_precision(roots[idx])));
|
||||||
|
fprintf(vlog_out, "module ivl_root_scope_%s;\n",
|
||||||
|
ivl_scope_basename(roots[idx]));
|
||||||
indent += indent_incr;
|
indent += indent_incr;
|
||||||
has_root_scope = 1;
|
|
||||||
}
|
|
||||||
/* Say this task/function has a parent so the
|
/* Say this task/function has a parent so the
|
||||||
* definition is emitted correctly. */
|
* definition is emitted correctly. */
|
||||||
emit_scope(roots[idx], roots[idx]);
|
emit_scope(roots[idx], roots[idx]);
|
||||||
|
|
||||||
|
indent -= indent_incr;
|
||||||
|
assert(indent == 0);
|
||||||
|
fprintf(vlog_out, "endmodule /* ivl_root_scope_%p */\n",
|
||||||
|
roots[idx]);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (has_root_scope) {
|
|
||||||
indent -= indent_incr;
|
|
||||||
assert(indent == 0);
|
|
||||||
fprintf(vlog_out, "endmodule /* ivl_root_scope */\n");
|
|
||||||
}
|
}
|
||||||
/* Emit the rest of the scope objects. */
|
/* Emit the rest of the scope objects. */
|
||||||
for (idx = 0; idx < nroots; idx += 1) emit_scope(roots[idx], 0);
|
for (idx = 0; idx < nroots; idx += 1) emit_scope(roots[idx], 0);
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef IVL_vlog95_priv_H
|
#ifndef IVL_vlog95_priv_H
|
||||||
#define IVL_vlog95_priv_H
|
#define IVL_vlog95_priv_H
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2010-2014 Cary R. (cygcary@yahoo.com)
|
* Copyright (C) 2010-2016 Cary R. (cygcary@yahoo.com)
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
|
@ -145,6 +145,11 @@ extern char * get_package_name(ivl_scope_t scope);
|
||||||
*/
|
*/
|
||||||
extern void get_sig_msb_lsb(ivl_signal_t sig, int *msb, int *lsb);
|
extern void get_sig_msb_lsb(ivl_signal_t sig, int *msb, int *lsb);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Convert a timescale value to a string.
|
||||||
|
*/
|
||||||
|
extern const char*get_time_const(int time_value);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Cleanup functions.
|
* Cleanup functions.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -47,8 +47,8 @@ CPPFLAGS = $(INCLUDE_PATH) @CPPFLAGS@ @DEFS@ @PICFLAG@
|
||||||
CFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CC@ @CFLAGS@
|
CFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CC@ @CFLAGS@
|
||||||
LDFLAGS = @LDFLAGS@
|
LDFLAGS = @LDFLAGS@
|
||||||
|
|
||||||
O = vvp.o draw_class.o draw_enum.o draw_mux.o draw_substitute.o draw_net_input.o \
|
O = vvp.o draw_class.o draw_delay.o draw_enum.o draw_mux.o draw_net_input.o \
|
||||||
draw_switch.o draw_ufunc.o draw_vpi.o \
|
draw_substitute.o draw_switch.o draw_ufunc.o draw_vpi.o \
|
||||||
eval_bool.o \
|
eval_bool.o \
|
||||||
eval_condit.o \
|
eval_condit.o \
|
||||||
eval_expr.o eval_object.o eval_real.o eval_string.o \
|
eval_expr.o eval_object.o eval_real.o eval_string.o \
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,127 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2016 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
# include "vvp_priv.h"
|
||||||
|
# include <assert.h>
|
||||||
|
# include <stdlib.h>
|
||||||
|
# include <string.h>
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function draws a BUFT to drive a constant delay value.
|
||||||
|
*/
|
||||||
|
static char* draw_const_net(void*ptr, char*suffix, uint64_t value)
|
||||||
|
{
|
||||||
|
char tmp[64];
|
||||||
|
char c4_value[69];
|
||||||
|
unsigned idx;
|
||||||
|
c4_value[0] = 'C';
|
||||||
|
c4_value[1] = '4';
|
||||||
|
c4_value[2] = '<';
|
||||||
|
for (idx = 0; idx < 64; idx += 1) {
|
||||||
|
c4_value[66-idx] = (value & 1) ? '1' : '0';
|
||||||
|
value >>= 1;
|
||||||
|
}
|
||||||
|
c4_value[67] = '>';
|
||||||
|
c4_value[68] = 0;
|
||||||
|
|
||||||
|
/* Make the constant an argument to a BUFT, which is
|
||||||
|
what we use to drive the value. */
|
||||||
|
fprintf(vvp_out, "L_%p/%s .functor BUFT 1, %s, C4<0>, C4<0>, C4<0>;\n",
|
||||||
|
ptr, suffix, c4_value);
|
||||||
|
snprintf(tmp, sizeof tmp, "L_%p/%s", ptr, suffix);
|
||||||
|
return strdup(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Draw the appropriate delay statement.
|
||||||
|
*/
|
||||||
|
void draw_delay(void*ptr, unsigned wid, const char*input, ivl_expr_t rise_exp,
|
||||||
|
ivl_expr_t fall_exp, ivl_expr_t decay_exp)
|
||||||
|
{
|
||||||
|
char tmp[64];
|
||||||
|
if (input == 0) {
|
||||||
|
snprintf(tmp, sizeof tmp, "L_%p/d", ptr);
|
||||||
|
input = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the delays are all constants then process them here. */
|
||||||
|
if (number_is_immediate(rise_exp, 64, 0) &&
|
||||||
|
number_is_immediate(fall_exp, 64, 0) &&
|
||||||
|
number_is_immediate(decay_exp, 64, 0)) {
|
||||||
|
|
||||||
|
assert(! number_is_unknown(rise_exp));
|
||||||
|
assert(! number_is_unknown(fall_exp));
|
||||||
|
assert(! number_is_unknown(decay_exp));
|
||||||
|
|
||||||
|
fprintf(vvp_out, "L_%p .delay %u "
|
||||||
|
"(%" PRIu64 ",%" PRIu64 ",%" PRIu64 ") %s;\n",
|
||||||
|
ptr, wid,
|
||||||
|
get_number_immediate64(rise_exp),
|
||||||
|
get_number_immediate64(fall_exp),
|
||||||
|
get_number_immediate64(decay_exp),
|
||||||
|
input);
|
||||||
|
|
||||||
|
/* For a variable delay we indicate only two delays by setting the
|
||||||
|
* decay time to zero. */
|
||||||
|
} else {
|
||||||
|
char*rise_const = 0;
|
||||||
|
char*fall_const = 0;
|
||||||
|
char*decay_const = 0;
|
||||||
|
const char*rise_str;
|
||||||
|
const char*fall_str;
|
||||||
|
const char*decay_str;
|
||||||
|
|
||||||
|
if (number_is_immediate(rise_exp, 64, 0)) {
|
||||||
|
uint64_t value = get_number_immediate64(rise_exp);
|
||||||
|
rise_str = rise_const = draw_const_net(ptr, "tr", value);
|
||||||
|
} else {
|
||||||
|
ivl_signal_t sig = ivl_expr_signal(rise_exp);
|
||||||
|
assert(sig && ivl_signal_dimensions(sig) == 0);
|
||||||
|
rise_str = draw_net_input(ivl_signal_nex(sig,0));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (number_is_immediate(fall_exp, 64, 0)) {
|
||||||
|
uint64_t value = get_number_immediate64(fall_exp);
|
||||||
|
fall_str = fall_const = draw_const_net(ptr, "tf", value);
|
||||||
|
} else {
|
||||||
|
ivl_signal_t sig = ivl_expr_signal(fall_exp);
|
||||||
|
assert(sig && ivl_signal_dimensions(sig) == 0);
|
||||||
|
fall_str = draw_net_input(ivl_signal_nex(sig,0));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (decay_exp == 0) {
|
||||||
|
decay_str = "0";
|
||||||
|
} else if (number_is_immediate(decay_exp, 64, 0)) {
|
||||||
|
uint64_t value = get_number_immediate64(decay_exp);
|
||||||
|
decay_str = decay_const = draw_const_net(ptr, "td", value);
|
||||||
|
} else {
|
||||||
|
ivl_signal_t sig = ivl_expr_signal(decay_exp);
|
||||||
|
assert(sig && ivl_signal_dimensions(sig) == 0);
|
||||||
|
decay_str = draw_net_input(ivl_signal_nex(sig,0));
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(vvp_out, "L_%p .delay %u %s, %s, %s, %s;\n",
|
||||||
|
ptr, wid, input, rise_str, fall_str, decay_str);
|
||||||
|
|
||||||
|
free(rise_const);
|
||||||
|
free(fall_const);
|
||||||
|
free(decay_const);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2012 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2002-2016 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -51,44 +51,8 @@ static void draw_lpm_mux_ab(ivl_lpm_t net, const char*muxz)
|
||||||
if (data_type_of_nexus(ivl_lpm_q(net)) == IVL_VT_REAL)
|
if (data_type_of_nexus(ivl_lpm_q(net)) == IVL_VT_REAL)
|
||||||
dly_width = 0;
|
dly_width = 0;
|
||||||
|
|
||||||
|
draw_delay(net, dly_width, 0, d_rise, d_fall, d_decay);
|
||||||
dly = "/d";
|
dly = "/d";
|
||||||
if (number_is_immediate(d_rise, 64, 0) &&
|
|
||||||
number_is_immediate(d_fall, 64, 0) &&
|
|
||||||
number_is_immediate(d_decay, 64, 0)) {
|
|
||||||
|
|
||||||
assert( ! number_is_unknown(d_rise));
|
|
||||||
assert( ! number_is_unknown(d_fall));
|
|
||||||
assert( ! number_is_unknown(d_decay));
|
|
||||||
|
|
||||||
fprintf(vvp_out, "L_%p .delay %u (%" PRIu64 ",%" PRIu64 ",%" PRIu64 ") L_%p/d;\n",
|
|
||||||
net, dly_width,
|
|
||||||
get_number_immediate64(d_rise),
|
|
||||||
get_number_immediate64(d_fall),
|
|
||||||
get_number_immediate64(d_decay), net);
|
|
||||||
} else {
|
|
||||||
ivl_signal_t sig;
|
|
||||||
// We do not currently support calculating the decay from
|
|
||||||
// the rise and fall variable delays.
|
|
||||||
assert(d_decay != 0);
|
|
||||||
assert(ivl_expr_type(d_rise) == IVL_EX_SIGNAL);
|
|
||||||
assert(ivl_expr_type(d_fall) == IVL_EX_SIGNAL);
|
|
||||||
assert(ivl_expr_type(d_decay) == IVL_EX_SIGNAL);
|
|
||||||
|
|
||||||
fprintf(vvp_out, "L_%p .delay %u L_%p/d",
|
|
||||||
net, dly_width, 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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
input[0] = draw_net_input(ivl_lpm_data(net,0));
|
input[0] = draw_net_input(ivl_lpm_data(net,0));
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2015 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2001-2016 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -330,9 +330,11 @@ static char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr)
|
||||||
|
|
||||||
cptr = ivl_nexus_ptr_con(nptr);
|
cptr = ivl_nexus_ptr_con(nptr);
|
||||||
if (cptr) {
|
if (cptr) {
|
||||||
|
char tmp[64];
|
||||||
char *result = 0;
|
char *result = 0;
|
||||||
ivl_expr_t d_rise, d_fall, d_decay;
|
ivl_expr_t d_rise, d_fall, d_decay;
|
||||||
unsigned dly_width = 0;
|
unsigned dly_width = 0;
|
||||||
|
char *dly;
|
||||||
|
|
||||||
/* Constants should have exactly 1 pin, with a literal value. */
|
/* Constants should have exactly 1 pin, with a literal value. */
|
||||||
assert(nptr_pin == 0);
|
assert(nptr_pin == 0);
|
||||||
|
|
@ -368,68 +370,17 @@ static char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr)
|
||||||
d_fall = ivl_const_delay(cptr, 1);
|
d_fall = ivl_const_delay(cptr, 1);
|
||||||
d_decay = ivl_const_delay(cptr, 2);
|
d_decay = ivl_const_delay(cptr, 2);
|
||||||
|
|
||||||
/* We have a delayed constant, so we need to build some code. */
|
dly = "";
|
||||||
if (d_rise != 0) {
|
if (d_rise != 0) {
|
||||||
char tmp[128];
|
draw_delay(cptr, dly_width, 0, d_rise, d_fall, d_decay);
|
||||||
fprintf(vvp_out, "L_%p/d .functor BUFT 1, %s, "
|
dly = "/d";
|
||||||
"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)) {
|
|
||||||
|
|
||||||
assert(! number_is_unknown(d_rise));
|
|
||||||
assert(! number_is_unknown(d_fall));
|
|
||||||
assert(! number_is_unknown(d_decay));
|
|
||||||
|
|
||||||
fprintf(vvp_out, "L_%p .delay %u "
|
|
||||||
"(%" PRIu64 ",%" PRIu64 ",%" PRIu64 ") L_%p/d;\n",
|
|
||||||
cptr, dly_width,
|
|
||||||
get_number_immediate64(d_rise),
|
|
||||||
get_number_immediate64(d_fall),
|
|
||||||
get_number_immediate64(d_decay), cptr);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
ivl_signal_t sig;
|
|
||||||
// We do not currently support calculating the decay
|
|
||||||
// from the rise and fall variable delays.
|
|
||||||
assert(d_decay != 0);
|
|
||||||
assert(ivl_expr_type(d_rise) == IVL_EX_SIGNAL);
|
|
||||||
assert(ivl_expr_type(d_fall) == IVL_EX_SIGNAL);
|
|
||||||
assert(ivl_expr_type(d_decay) == IVL_EX_SIGNAL);
|
|
||||||
|
|
||||||
fprintf(vvp_out, "L_%p .delay %u L_%p/d",
|
|
||||||
cptr, dly_width, 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);
|
|
||||||
}
|
}
|
||||||
|
fprintf(vvp_out, "L_%p%s .functor BUFT 1, %s, C4<0>, C4<0>, C4<0>;\n",
|
||||||
snprintf(tmp, sizeof tmp, "L_%p", cptr);
|
cptr, dly, result);
|
||||||
result = strdup(tmp);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
char tmp[64];
|
|
||||||
fprintf(vvp_out, "L_%p .functor BUFT 1, %s, "
|
|
||||||
"C4<0>, C4<0>, C4<0>;\n", cptr, result);
|
|
||||||
free(result);
|
free(result);
|
||||||
|
|
||||||
snprintf(tmp, sizeof tmp, "L_%p", cptr);
|
snprintf(tmp, sizeof tmp, "L_%p", cptr);
|
||||||
result = strdup(tmp);
|
return strdup(tmp);
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lpm = ivl_nexus_ptr_lpm(nptr);
|
lpm = ivl_nexus_ptr_lpm(nptr);
|
||||||
|
|
@ -711,6 +662,8 @@ static void draw_net_input_x(ivl_nexus_t nex,
|
||||||
tmp += strlen(tmp);
|
tmp += strlen(tmp);
|
||||||
switch (res) {
|
switch (res) {
|
||||||
case IVL_SIT_TRI:
|
case IVL_SIT_TRI:
|
||||||
|
case IVL_SIT_TRIAND:
|
||||||
|
case IVL_SIT_TRIOR:
|
||||||
case IVL_SIT_UWIRE:
|
case IVL_SIT_UWIRE:
|
||||||
for (jdx = 0 ; jdx < wid ; jdx += 1)
|
for (jdx = 0 ; jdx < wid ; jdx += 1)
|
||||||
*tmp++ = 'z';
|
*tmp++ = 'z';
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008-2010,2012 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2008-2016 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -38,18 +38,6 @@ void draw_switch_in_scope(ivl_switch_t sw)
|
||||||
ivl_expr_t fall_exp = ivl_switch_delay(sw, 1);
|
ivl_expr_t fall_exp = ivl_switch_delay(sw, 1);
|
||||||
ivl_expr_t decay_exp= ivl_switch_delay(sw, 2);
|
ivl_expr_t decay_exp= ivl_switch_delay(sw, 2);
|
||||||
|
|
||||||
if ((rise_exp || fall_exp || decay_exp) &&
|
|
||||||
(!number_is_immediate(rise_exp, 64, 0) ||
|
|
||||||
number_is_unknown(rise_exp) ||
|
|
||||||
!number_is_immediate(fall_exp, 64, 0) ||
|
|
||||||
number_is_unknown(fall_exp) ||
|
|
||||||
!number_is_immediate(decay_exp, 64, 0) ||
|
|
||||||
number_is_unknown(decay_exp))) {
|
|
||||||
fprintf(stderr, "%s:%u: error: Invalid tranif delay expression.\n",
|
|
||||||
ivl_switch_file(sw), ivl_switch_lineno(sw));
|
|
||||||
vvp_errors += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
island = ivl_switch_island(sw);
|
island = ivl_switch_island(sw);
|
||||||
if (ivl_island_flag_test(island, 0) == 0)
|
if (ivl_island_flag_test(island, 0) == 0)
|
||||||
draw_tran_island(island);
|
draw_tran_island(island);
|
||||||
|
|
@ -67,24 +55,18 @@ void draw_switch_in_scope(ivl_switch_t sw)
|
||||||
char str_e_buf[4 + 2*sizeof(void*)];
|
char str_e_buf[4 + 2*sizeof(void*)];
|
||||||
|
|
||||||
if (enable && rise_exp) {
|
if (enable && rise_exp) {
|
||||||
assert(fall_exp && decay_exp);
|
|
||||||
|
|
||||||
/* If the enable has a delay, then generate a .delay
|
/* If the enable has a delay, then generate a .delay
|
||||||
node to delay the input by the specified amount. Do
|
node to delay the input by the specified amount. Do
|
||||||
the delay outside of the island so that the island
|
the delay outside of the island so that the island
|
||||||
processing doesn't have to deal with it. */
|
processing doesn't have to deal with it. */
|
||||||
const char*raw = draw_net_input(enable);
|
const char*raw = draw_net_input(enable);
|
||||||
|
|
||||||
|
draw_delay(sw, 1, raw, rise_exp, fall_exp, decay_exp);
|
||||||
|
|
||||||
snprintf(str_e_buf, sizeof str_e_buf, "p%p", sw);
|
snprintf(str_e_buf, sizeof str_e_buf, "p%p", sw);
|
||||||
str_e = str_e_buf;
|
str_e = str_e_buf;
|
||||||
|
|
||||||
fprintf(vvp_out, "%s/d .delay 1 "
|
fprintf(vvp_out, "%s .import I%p, L_%p;\n", str_e, island, sw);
|
||||||
"(%" PRIu64 ",%" PRIu64 ",%" PRIu64 ") %s;\n",
|
|
||||||
str_e, get_number_immediate64(rise_exp),
|
|
||||||
get_number_immediate64(fall_exp),
|
|
||||||
get_number_immediate64(decay_exp), raw);
|
|
||||||
|
|
||||||
fprintf(vvp_out, "%s .import I%p, %s/d;\n", str_e, island, str_e);
|
|
||||||
|
|
||||||
} else if (enable) {
|
} else if (enable) {
|
||||||
str_e = draw_island_net_input(island, enable);
|
str_e = draw_island_net_input(island, enable);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2011-2015 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2011-2016 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -183,17 +183,17 @@ static void get_vec_from_lval(ivl_statement_t net, struct vec_slice_info*slices)
|
||||||
unsigned wid = ivl_stmt_lwidth(net);
|
unsigned wid = ivl_stmt_lwidth(net);
|
||||||
|
|
||||||
cur_bit = 0;
|
cur_bit = 0;
|
||||||
for (lidx = 0 ; lidx < ivl_stmt_lvals(net) ; lidx += 1) {
|
for (lidx = ivl_stmt_lvals(net) ; lidx > 0 ; lidx -= 1) {
|
||||||
ivl_lval_t lval;
|
ivl_lval_t lval;
|
||||||
unsigned bit_limit = wid - cur_bit;
|
unsigned bit_limit = wid - cur_bit;
|
||||||
|
|
||||||
lval = ivl_stmt_lval(net, lidx);
|
lval = ivl_stmt_lval(net, lidx-1);
|
||||||
|
|
||||||
if (bit_limit > ivl_lval_width(lval))
|
if (bit_limit > ivl_lval_width(lval))
|
||||||
bit_limit = ivl_lval_width(lval);
|
bit_limit = ivl_lval_width(lval);
|
||||||
|
|
||||||
get_vec_from_lval_slice(lval, slices+lidx, bit_limit);
|
get_vec_from_lval_slice(lval, slices+lidx-1, bit_limit);
|
||||||
if (lidx > 0) {
|
if (cur_bit > 0) {
|
||||||
fprintf(vvp_out, " %%concat/vec4;\n");
|
fprintf(vvp_out, " %%concat/vec4;\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -555,28 +555,130 @@ static int show_stmt_assign_vector(ivl_statement_t net)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
enum real_lval_type_e {
|
||||||
* This function assigns a value to a real variable. This is destined
|
REAL_NO_TYPE = 0,
|
||||||
* for /dev/null when typed ivl_signal_t takes over all the real
|
REAL_SIMPLE_WORD,
|
||||||
* variable support.
|
REAL_MEMORY_WORD_STATIC,
|
||||||
*/
|
REAL_MEMORY_WORD_DYNAMIC
|
||||||
static int show_stmt_assign_sig_real(ivl_statement_t net)
|
};
|
||||||
|
|
||||||
|
struct real_lval_info {
|
||||||
|
enum real_lval_type_e type;
|
||||||
|
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
unsigned long use_word;
|
||||||
|
} simple_word;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
unsigned long use_word;
|
||||||
|
} memory_word_static;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
/* Index reg that holds the memory word index */
|
||||||
|
int word_idx_reg;
|
||||||
|
/* Stored x/non-x flag */
|
||||||
|
unsigned x_flag;
|
||||||
|
} memory_word_dynamic;
|
||||||
|
} u_;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void get_real_from_lval(ivl_lval_t lval, struct real_lval_info*slice)
|
||||||
|
{
|
||||||
|
ivl_signal_t sig = ivl_lval_sig(lval);
|
||||||
|
ivl_expr_t word_ix = ivl_lval_idx(lval);
|
||||||
|
unsigned long use_word = 0;
|
||||||
|
|
||||||
|
/* If the word index is a constant expression, then evaluate
|
||||||
|
it to select the word, and pay no further heed to the
|
||||||
|
expression itself. */
|
||||||
|
if (word_ix && number_is_immediate(word_ix, IMM_WID, 0)) {
|
||||||
|
assert(! number_is_unknown(word_ix));
|
||||||
|
use_word = get_number_immediate(word_ix);
|
||||||
|
word_ix = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ivl_signal_dimensions(sig)==0 && word_ix==0) {
|
||||||
|
|
||||||
|
slice->type = REAL_SIMPLE_WORD;
|
||||||
|
slice->u_.simple_word.use_word = use_word;
|
||||||
|
fprintf(vvp_out, " %%load/real v%p_%lu;\n", sig, use_word);
|
||||||
|
|
||||||
|
} else if (ivl_signal_dimensions(sig) > 0 && word_ix == 0) {
|
||||||
|
|
||||||
|
slice->type = REAL_MEMORY_WORD_STATIC;
|
||||||
|
slice->u_.memory_word_static.use_word = use_word;
|
||||||
|
if (use_word < ivl_signal_array_count(sig)) {
|
||||||
|
fprintf(vvp_out, " %%ix/load 3, %lu, 0;\n",
|
||||||
|
use_word);
|
||||||
|
fprintf(vvp_out, " %%load/reala v%p, 3;\n", sig);
|
||||||
|
} else {
|
||||||
|
fprintf(vvp_out, " %%pushi/real 0, 0;\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (ivl_signal_dimensions(sig) > 0 && word_ix != 0) {
|
||||||
|
|
||||||
|
slice->type = REAL_MEMORY_WORD_DYNAMIC;
|
||||||
|
|
||||||
|
slice->u_.memory_word_dynamic.word_idx_reg = allocate_word();
|
||||||
|
slice->u_.memory_word_dynamic.x_flag = allocate_flag();
|
||||||
|
|
||||||
|
draw_eval_expr_into_integer(word_ix, slice->u_.memory_word_dynamic.word_idx_reg);
|
||||||
|
fprintf(vvp_out, " %%flag_mov %u, 4;\n", slice->u_.memory_word_dynamic.x_flag);
|
||||||
|
fprintf(vvp_out, " %%load/reala v%p, %d;\n", sig, slice->u_.memory_word_dynamic.word_idx_reg);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void put_real_to_lval(ivl_lval_t lval, struct real_lval_info*slice)
|
||||||
|
{
|
||||||
|
ivl_signal_t sig = ivl_lval_sig(lval);
|
||||||
|
|
||||||
|
switch (slice->type) {
|
||||||
|
default:
|
||||||
|
fprintf(vvp_out, " ; XXXX slice->type=%d\n", slice->type);
|
||||||
|
assert(0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case REAL_SIMPLE_WORD:
|
||||||
|
fprintf(vvp_out, " %%store/real v%p_%lu;\n",
|
||||||
|
sig, slice->u_.simple_word.use_word);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case REAL_MEMORY_WORD_STATIC:
|
||||||
|
if (slice->u_.memory_word_static.use_word < ivl_signal_array_count(sig)) {
|
||||||
|
int word_idx = allocate_word();
|
||||||
|
fprintf(vvp_out," %%flag_set/imm 4, 0;\n");
|
||||||
|
fprintf(vvp_out," %%ix/load %d, %lu, 0;\n", word_idx, slice->u_.memory_word_static.use_word);
|
||||||
|
fprintf(vvp_out," %%store/reala v%p, %d;\n", sig, word_idx);
|
||||||
|
clr_word(word_idx);
|
||||||
|
} else {
|
||||||
|
fprintf(vvp_out," ; Skip this slice write to v%p [%lu]\n", sig, slice->u_.memory_word_static.use_word);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case REAL_MEMORY_WORD_DYNAMIC:
|
||||||
|
fprintf(vvp_out, " %%flag_mov 4, %u;\n", slice->u_.memory_word_dynamic.x_flag);
|
||||||
|
fprintf(vvp_out, " %%store/reala v%p, %d;\n", sig, slice->u_.memory_word_dynamic.word_idx_reg);
|
||||||
|
clr_word(slice->u_.memory_word_dynamic.word_idx_reg);
|
||||||
|
clr_flag(slice->u_.memory_word_dynamic.x_flag);
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void store_real_to_lval(ivl_lval_t lval)
|
||||||
{
|
{
|
||||||
ivl_lval_t lval;
|
|
||||||
ivl_signal_t var;
|
ivl_signal_t var;
|
||||||
|
|
||||||
assert(ivl_stmt_opcode(net) == 0);
|
|
||||||
|
|
||||||
draw_eval_real(ivl_stmt_rval(net));
|
|
||||||
|
|
||||||
assert(ivl_stmt_lvals(net) == 1);
|
|
||||||
lval = ivl_stmt_lval(net, 0);
|
|
||||||
var = ivl_lval_sig(lval);
|
var = ivl_lval_sig(lval);
|
||||||
assert(var != 0);
|
assert(var != 0);
|
||||||
|
|
||||||
if (ivl_signal_dimensions(var) == 0) {
|
if (ivl_signal_dimensions(var) == 0) {
|
||||||
fprintf(vvp_out, " %%store/real v%p_0;\n", var);
|
fprintf(vvp_out, " %%store/real v%p_0;\n", var);
|
||||||
return 0;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// For now, only support 1-dimensional arrays.
|
// For now, only support 1-dimensional arrays.
|
||||||
|
|
@ -612,7 +714,66 @@ static int show_stmt_assign_sig_real(ivl_statement_t net)
|
||||||
}
|
}
|
||||||
|
|
||||||
clr_word(word_ix);
|
clr_word(word_ix);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function assigns a value to a real variable. This is destined
|
||||||
|
* for /dev/null when typed ivl_signal_t takes over all the real
|
||||||
|
* variable support.
|
||||||
|
*/
|
||||||
|
static int show_stmt_assign_sig_real(ivl_statement_t net)
|
||||||
|
{
|
||||||
|
struct real_lval_info*slice = 0;
|
||||||
|
ivl_lval_t lval;
|
||||||
|
|
||||||
|
assert(ivl_stmt_lvals(net) == 1);
|
||||||
|
lval = ivl_stmt_lval(net, 0);
|
||||||
|
|
||||||
|
/* If this is a compressed assignment, then get the contents
|
||||||
|
of the l-value. We need this value as part of the r-value
|
||||||
|
calculation. */
|
||||||
|
if (ivl_stmt_opcode(net) != 0) {
|
||||||
|
fprintf(vvp_out, " ; show_stmt_assign_real: Get l-value for compressed %c= operand\n", ivl_stmt_opcode(net));
|
||||||
|
slice = calloc(1, sizeof(struct real_lval_info));
|
||||||
|
get_real_from_lval(lval, slice);
|
||||||
|
}
|
||||||
|
|
||||||
|
draw_eval_real(ivl_stmt_rval(net));
|
||||||
|
|
||||||
|
switch (ivl_stmt_opcode(net)) {
|
||||||
|
case 0:
|
||||||
|
store_real_to_lval(lval);
|
||||||
|
if (slice) free(slice);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case '+':
|
||||||
|
fprintf(vvp_out, " %%add/wr;\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '-':
|
||||||
|
fprintf(vvp_out, " %%sub/wr;\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '*':
|
||||||
|
fprintf(vvp_out, " %%mul/wr;\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '/':
|
||||||
|
fprintf(vvp_out, " %%div/wr;\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '%':
|
||||||
|
fprintf(vvp_out, " %%mod/wr;\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
fprintf(vvp_out, "; UNSUPPORTED ASSIGNMENT OPCODE: %c\n", ivl_stmt_opcode(net));
|
||||||
|
assert(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
put_real_to_lval(lval, slice);
|
||||||
|
free(slice);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -256,6 +256,13 @@ extern void show_stmt_file_line(ivl_statement_t net, const char*desc);
|
||||||
extern int test_immediate_vec4_ok(ivl_expr_t expr);
|
extern int test_immediate_vec4_ok(ivl_expr_t expr);
|
||||||
extern void draw_immediate_vec4(ivl_expr_t expr, const char*opcode);
|
extern void draw_immediate_vec4(ivl_expr_t expr, const char*opcode);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Draw a delay statement.
|
||||||
|
*/
|
||||||
|
extern void draw_delay(void*ptr, unsigned wid, const char*input,
|
||||||
|
ivl_expr_t rise_exp, ivl_expr_t fall_exp,
|
||||||
|
ivl_expr_t decay_exp);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These functions manage word register allocation.
|
* These functions manage word register allocation.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2015 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2001-2016 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -225,6 +225,15 @@ static void assign_to_lvector(ivl_lval_t lval,
|
||||||
|
|
||||||
const unsigned long use_word = 0;
|
const unsigned long use_word = 0;
|
||||||
|
|
||||||
|
if (ivl_signal_type(sig) == IVL_SIT_UWIRE) {
|
||||||
|
fprintf(stderr, "%s:%u: tgt-vvp sorry: V10 does not support "
|
||||||
|
"mixed continuous and non-blocking assignments to "
|
||||||
|
"different parts of the same vector (%s).\n",
|
||||||
|
ivl_signal_file(sig), ivl_signal_lineno(sig),
|
||||||
|
ivl_signal_basename(sig));
|
||||||
|
vvp_errors += 1;
|
||||||
|
}
|
||||||
|
|
||||||
// Detect the case that this is actually a non-blocking assign
|
// Detect the case that this is actually a non-blocking assign
|
||||||
// to an array word. In that case, run off somewhere else to
|
// to an array word. In that case, run off somewhere else to
|
||||||
// deal with it.
|
// deal with it.
|
||||||
|
|
@ -2298,6 +2307,7 @@ int draw_process(ivl_process_t net, void*x)
|
||||||
ivl_scope_t scope = ivl_process_scope(net);
|
ivl_scope_t scope = ivl_process_scope(net);
|
||||||
ivl_statement_t stmt = ivl_process_stmt(net);
|
ivl_statement_t stmt = ivl_process_stmt(net);
|
||||||
|
|
||||||
|
int init_flag = 0;
|
||||||
int push_flag = 0;
|
int push_flag = 0;
|
||||||
|
|
||||||
(void)x; /* Parameter is not used. */
|
(void)x; /* Parameter is not used. */
|
||||||
|
|
@ -2306,6 +2316,12 @@ int draw_process(ivl_process_t net, void*x)
|
||||||
|
|
||||||
ivl_attribute_t attr = ivl_process_attr_val(net, idx);
|
ivl_attribute_t attr = ivl_process_attr_val(net, idx);
|
||||||
|
|
||||||
|
if (strcmp(attr->key, "_ivl_schedule_init") == 0) {
|
||||||
|
|
||||||
|
init_flag = 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if (strcmp(attr->key, "_ivl_schedule_push") == 0) {
|
if (strcmp(attr->key, "_ivl_schedule_push") == 0) {
|
||||||
|
|
||||||
push_flag = 1;
|
push_flag = 1;
|
||||||
|
|
@ -2349,7 +2365,9 @@ int draw_process(ivl_process_t net, void*x)
|
||||||
|
|
||||||
case IVL_PR_INITIAL:
|
case IVL_PR_INITIAL:
|
||||||
case IVL_PR_ALWAYS:
|
case IVL_PR_ALWAYS:
|
||||||
if (push_flag) {
|
if (init_flag) {
|
||||||
|
fprintf(vvp_out, " .thread T_%u, $init;\n", thread_count);
|
||||||
|
} else if (push_flag) {
|
||||||
fprintf(vvp_out, " .thread T_%u, $push;\n", thread_count);
|
fprintf(vvp_out, " .thread T_%u, $push;\n", thread_count);
|
||||||
} else {
|
} else {
|
||||||
fprintf(vvp_out, " .thread T_%u;\n", thread_count);
|
fprintf(vvp_out, " .thread T_%u;\n", thread_count);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2015 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2001-2016 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -669,7 +669,7 @@ static void draw_net_in_scope(ivl_signal_t sig)
|
||||||
swapped ? last : first );
|
swapped ? last : first );
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(vvp_out, "v%p_%u .alias%s v%p %u, %d %d, "
|
fprintf(vvp_out, "v%p_%u .net%s v%p %u, %d %d, "
|
||||||
"v%p_%u; Alias to %s\n", sig, iword,
|
"v%p_%u; Alias to %s\n", sig, iword,
|
||||||
datatype_flag, sig, iword, msb, lsb,
|
datatype_flag, sig, iword, msb, lsb,
|
||||||
nex_data->net, nex_data->net_word,
|
nex_data->net, nex_data->net_word,
|
||||||
|
|
@ -717,7 +717,7 @@ static unsigned need_delay(ivl_net_logic_t lptr)
|
||||||
/*
|
/*
|
||||||
* Draw the appropriate delay statement. Returns zero if there is not a delay.
|
* Draw the appropriate delay statement. Returns zero if there is not a delay.
|
||||||
*/
|
*/
|
||||||
static void draw_delay(ivl_net_logic_t lptr)
|
static void draw_logic_delay(ivl_net_logic_t lptr)
|
||||||
{
|
{
|
||||||
ivl_expr_t rise_exp = ivl_logic_delay(lptr, 0);
|
ivl_expr_t rise_exp = ivl_logic_delay(lptr, 0);
|
||||||
ivl_expr_t fall_exp = ivl_logic_delay(lptr, 1);
|
ivl_expr_t fall_exp = ivl_logic_delay(lptr, 1);
|
||||||
|
|
@ -730,49 +730,7 @@ static void draw_delay(ivl_net_logic_t lptr)
|
||||||
delay_wid = 0;
|
delay_wid = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the delays are all constants then process them here. */
|
draw_delay(lptr, delay_wid, 0, rise_exp, fall_exp, decay_exp);
|
||||||
if (number_is_immediate(rise_exp, 64, 0) &&
|
|
||||||
number_is_immediate(fall_exp, 64, 0) &&
|
|
||||||
number_is_immediate(decay_exp, 64, 0)) {
|
|
||||||
|
|
||||||
assert(! number_is_unknown(rise_exp));
|
|
||||||
assert(! number_is_unknown(fall_exp));
|
|
||||||
assert(! number_is_unknown(decay_exp));
|
|
||||||
|
|
||||||
fprintf(vvp_out, "L_%p .delay %u "
|
|
||||||
"(%" PRIu64 ",%" PRIu64 ",%" PRIu64 ") L_%p/d;\n",
|
|
||||||
lptr, delay_wid,
|
|
||||||
get_number_immediate64(rise_exp),
|
|
||||||
get_number_immediate64(fall_exp),
|
|
||||||
get_number_immediate64(decay_exp), lptr);
|
|
||||||
/* For a variable delay we indicate only two delays by setting the
|
|
||||||
* decay time to zero. */
|
|
||||||
} else {
|
|
||||||
ivl_signal_t sig;
|
|
||||||
assert(ivl_expr_type(rise_exp) == IVL_EX_SIGNAL);
|
|
||||||
assert(ivl_expr_type(fall_exp) == IVL_EX_SIGNAL);
|
|
||||||
assert((decay_exp == 0) ||
|
|
||||||
(ivl_expr_type(decay_exp) == IVL_EX_SIGNAL));
|
|
||||||
|
|
||||||
fprintf(vvp_out, "L_%p .delay %u L_%p/d", lptr, delay_wid, lptr);
|
|
||||||
|
|
||||||
sig = ivl_expr_signal(rise_exp);
|
|
||||||
assert(ivl_signal_dimensions(sig) == 0);
|
|
||||||
fprintf(vvp_out, ", %s", draw_net_input(ivl_signal_nex(sig,0)));
|
|
||||||
|
|
||||||
sig = ivl_expr_signal(fall_exp);
|
|
||||||
assert(ivl_signal_dimensions(sig) == 0);
|
|
||||||
fprintf(vvp_out, ", %s", draw_net_input(ivl_signal_nex(sig,0)));
|
|
||||||
|
|
||||||
if (decay_exp) {
|
|
||||||
sig = ivl_expr_signal(decay_exp);
|
|
||||||
assert(ivl_signal_dimensions(sig) == 0);
|
|
||||||
fprintf(vvp_out, ", %s;\n",
|
|
||||||
draw_net_input(ivl_signal_nex(sig,0)));
|
|
||||||
} else {
|
|
||||||
fprintf(vvp_out, ", 0;\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void draw_udp_def(ivl_udp_t udp)
|
static void draw_udp_def(ivl_udp_t udp)
|
||||||
|
|
@ -908,7 +866,7 @@ static void draw_udp_in_scope(ivl_net_logic_t lptr)
|
||||||
fprintf(vvp_out, ";\n");
|
fprintf(vvp_out, ";\n");
|
||||||
|
|
||||||
/* Generate a delay when needed. */
|
/* Generate a delay when needed. */
|
||||||
if (need_delay_flag) draw_delay(lptr);
|
if (need_delay_flag) draw_logic_delay(lptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void draw_logic_in_scope(ivl_net_logic_t lptr)
|
static void draw_logic_in_scope(ivl_net_logic_t lptr)
|
||||||
|
|
@ -1112,7 +1070,7 @@ static void draw_logic_in_scope(ivl_net_logic_t lptr)
|
||||||
free(input_strings);
|
free(input_strings);
|
||||||
|
|
||||||
/* Generate a delay when needed. */
|
/* Generate a delay when needed. */
|
||||||
if (need_delay_flag) draw_delay(lptr);
|
if (need_delay_flag) draw_logic_delay(lptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void draw_event_in_scope(ivl_event_t obj)
|
static void draw_event_in_scope(ivl_event_t obj)
|
||||||
|
|
@ -1312,20 +1270,8 @@ static const char* draw_lpm_output_delay(ivl_lpm_t net, ivl_variable_type_t dt)
|
||||||
|
|
||||||
const char*dly = "";
|
const char*dly = "";
|
||||||
if (d_rise != 0) {
|
if (d_rise != 0) {
|
||||||
assert(number_is_immediate(d_rise, 64, 0));
|
draw_delay(net, width, 0, d_rise, d_fall, d_decay);
|
||||||
assert(number_is_immediate(d_fall, 64, 0));
|
|
||||||
assert(number_is_immediate(d_decay, 64, 0));
|
|
||||||
|
|
||||||
assert(! number_is_unknown(d_rise));
|
|
||||||
assert(! number_is_unknown(d_fall));
|
|
||||||
assert(! number_is_unknown(d_decay));
|
|
||||||
|
|
||||||
dly = "/d";
|
dly = "/d";
|
||||||
fprintf(vvp_out, "L_%p .delay %u (%" PRIu64 ",%" PRIu64 ",%" PRIu64 ")"
|
|
||||||
" L_%p/d;\n", net, width,
|
|
||||||
get_number_immediate64(d_rise),
|
|
||||||
get_number_immediate64(d_fall),
|
|
||||||
get_number_immediate64(d_decay), net);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return dly;
|
return dly;
|
||||||
|
|
|
||||||
65
vpi/fstapi.c
65
vpi/fstapi.c
|
|
@ -3074,6 +3074,7 @@ uint32_t *rvat_chain_table_lengths;
|
||||||
uint64_t rvat_vc_maxhandle;
|
uint64_t rvat_vc_maxhandle;
|
||||||
off_t rvat_vc_start;
|
off_t rvat_vc_start;
|
||||||
uint32_t *rvat_sig_offs;
|
uint32_t *rvat_sig_offs;
|
||||||
|
int rvat_packtype;
|
||||||
|
|
||||||
uint32_t rvat_chain_len;
|
uint32_t rvat_chain_len;
|
||||||
unsigned char *rvat_chain_mem;
|
unsigned char *rvat_chain_mem;
|
||||||
|
|
@ -5886,6 +5887,7 @@ if(frame_uclen == frame_clen)
|
||||||
|
|
||||||
xc->rvat_vc_maxhandle = fstReaderVarint64(xc->f);
|
xc->rvat_vc_maxhandle = fstReaderVarint64(xc->f);
|
||||||
xc->rvat_vc_start = ftello(xc->f); /* points to '!' character */
|
xc->rvat_vc_start = ftello(xc->f); /* points to '!' character */
|
||||||
|
xc->rvat_packtype = fgetc(xc->f);
|
||||||
|
|
||||||
#ifdef FST_DEBUG
|
#ifdef FST_DEBUG
|
||||||
fprintf(stderr, "\tframe_uclen: %d, frame_clen: %d, frame_maxhandle: %d\n",
|
fprintf(stderr, "\tframe_uclen: %d, frame_clen: %d, frame_maxhandle: %d\n",
|
||||||
|
|
@ -5910,7 +5912,53 @@ xc->rvat_chain_table_lengths = calloc((xc->rvat_vc_maxhandle+1), sizeof(uint32_t
|
||||||
pnt = chain_cmem;
|
pnt = chain_cmem;
|
||||||
idx = 0;
|
idx = 0;
|
||||||
pval = 0;
|
pval = 0;
|
||||||
do
|
|
||||||
|
if(sectype == FST_BL_VCDATA_DYN_ALIAS2)
|
||||||
|
{
|
||||||
|
uint32_t prev_alias = 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
int skiplen;
|
||||||
|
|
||||||
|
if(*pnt & 0x01)
|
||||||
|
{
|
||||||
|
int64_t shval = fstGetSVarint64(pnt, &skiplen) >> 1;
|
||||||
|
if(shval > 0)
|
||||||
|
{
|
||||||
|
pval = xc->rvat_chain_table[idx] = pval + shval;
|
||||||
|
if(idx) { xc->rvat_chain_table_lengths[pidx] = pval - xc->rvat_chain_table[pidx]; }
|
||||||
|
pidx = idx++;
|
||||||
|
}
|
||||||
|
else if(shval < 0)
|
||||||
|
{
|
||||||
|
xc->rvat_chain_table[idx] = 0; /* need to explicitly zero as calloc above might not run */
|
||||||
|
xc->rvat_chain_table_lengths[idx] = prev_alias = shval; /* because during this loop iter would give stale data! */
|
||||||
|
idx++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
xc->rvat_chain_table[idx] = 0; /* need to explicitly zero as calloc above might not run */
|
||||||
|
xc->rvat_chain_table_lengths[idx] = prev_alias; /* because during this loop iter would give stale data! */
|
||||||
|
idx++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uint64_t val = fstGetVarint32(pnt, &skiplen);
|
||||||
|
|
||||||
|
fstHandle loopcnt = val >> 1;
|
||||||
|
for(i=0;i<loopcnt;i++)
|
||||||
|
{
|
||||||
|
xc->rvat_chain_table[idx++] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pnt += skiplen;
|
||||||
|
} while (pnt != (chain_cmem + chain_clen));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
do
|
||||||
{
|
{
|
||||||
int skiplen;
|
int skiplen;
|
||||||
uint64_t val = fstGetVarint32(pnt, &skiplen);
|
uint64_t val = fstGetVarint32(pnt, &skiplen);
|
||||||
|
|
@ -5941,6 +5989,7 @@ do
|
||||||
|
|
||||||
pnt += skiplen;
|
pnt += skiplen;
|
||||||
} while (pnt != (chain_cmem + chain_clen));
|
} while (pnt != (chain_cmem + chain_clen));
|
||||||
|
}
|
||||||
|
|
||||||
free(chain_cmem);
|
free(chain_cmem);
|
||||||
xc->rvat_chain_table[idx] = indx_pos - xc->rvat_vc_start;
|
xc->rvat_chain_table[idx] = indx_pos - xc->rvat_vc_start;
|
||||||
|
|
@ -6004,10 +6053,20 @@ if(!xc->rvat_chain_mem)
|
||||||
unsigned char *mc = malloc(xc->rvat_chain_table_lengths[facidx]);
|
unsigned char *mc = malloc(xc->rvat_chain_table_lengths[facidx]);
|
||||||
unsigned long destlen = xc->rvat_chain_len;
|
unsigned long destlen = xc->rvat_chain_len;
|
||||||
unsigned long sourcelen = xc->rvat_chain_table_lengths[facidx];
|
unsigned long sourcelen = xc->rvat_chain_table_lengths[facidx];
|
||||||
int rc;
|
int rc = Z_OK;
|
||||||
|
|
||||||
fstFread(mc, xc->rvat_chain_table_lengths[facidx], 1, xc->f);
|
fstFread(mc, xc->rvat_chain_table_lengths[facidx], 1, xc->f);
|
||||||
rc = uncompress(mu, &destlen, mc, sourcelen);
|
|
||||||
|
switch(xc->rvat_packtype)
|
||||||
|
{
|
||||||
|
case '4': rc = (destlen == (unsigned long)LZ4_decompress_safe_partial((char *)mc, (char *)mu, sourcelen, destlen, destlen)) ? Z_OK : Z_DATA_ERROR;
|
||||||
|
break;
|
||||||
|
case 'F': fastlz_decompress(mc, sourcelen, mu, destlen); /* rc appears unreliable */
|
||||||
|
break;
|
||||||
|
default: rc = uncompress(mu, &destlen, mc, sourcelen);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
free(mc);
|
free(mc);
|
||||||
|
|
||||||
if(rc != Z_OK)
|
if(rc != Z_OK)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2003-2012 Tony Bybell.
|
* Copyright (c) 2003-2016 Tony Bybell.
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
* copy of this software and associated documentation files (the "Software"),
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
|
@ -1029,12 +1029,12 @@ for(i=len;i>0;i--)
|
||||||
|
|
||||||
if(!i)
|
if(!i)
|
||||||
{
|
{
|
||||||
sprintf(tname, "%s_%03d.lxt", lt->lxtname, ++lt->break_number);
|
sprintf(tname, "%s_%03u.lxt", lt->lxtname, ++lt->break_number);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
memcpy(tname, lt->lxtname, i);
|
memcpy(tname, lt->lxtname, i);
|
||||||
sprintf(tname+i, "_%03d.lxt", ++lt->break_number);
|
sprintf(tname+i, "_%03u.lxt", ++lt->break_number);
|
||||||
}
|
}
|
||||||
|
|
||||||
f2 = fopen(tname, "wb");
|
f2 = fopen(tname, "wb");
|
||||||
|
|
|
||||||
|
|
@ -1971,12 +1971,7 @@ static PLI_INT32 sys_printtimescale_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
|
||||||
item = vpi_scan(argv);
|
item = vpi_scan(argv);
|
||||||
vpi_free_object(argv);
|
vpi_free_object(argv);
|
||||||
}
|
}
|
||||||
|
scope = sys_func_module(item);
|
||||||
if (vpi_get(vpiType, item) != vpiModule) {
|
|
||||||
scope = vpi_handle(vpiModule, item);
|
|
||||||
} else {
|
|
||||||
scope = item;
|
|
||||||
}
|
|
||||||
|
|
||||||
vpi_printf("Time scale of (%s) is ", vpi_get_str(vpiFullName, item));
|
vpi_printf("Time scale of (%s) is ", vpi_get_str(vpiFullName, item));
|
||||||
vpi_printf("%s / ", pts_convert(vpi_get(vpiTimeUnit, scope)));
|
vpi_printf("%s / ", pts_convert(vpi_get(vpiTimeUnit, scope)));
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@ static PLI_INT32 missing_optional_compiletf(ICARUS_VPI_CONST PLI_BYTE8* name)
|
||||||
{
|
{
|
||||||
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
|
vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
|
||||||
|
|
||||||
vpi_printf("SORRY: %s:%d: %s() is not available in Icarus verilog.\n",
|
vpi_printf("SORRY: %s:%d: %s() is not available in Icarus Verilog.\n",
|
||||||
vpi_get_str(vpiFile, callh), (int)vpi_get(vpiLineNo, callh),
|
vpi_get_str(vpiFile, callh), (int)vpi_get(vpiLineNo, callh),
|
||||||
name);
|
name);
|
||||||
vpi_control(vpiFinish, 1);
|
vpi_control(vpiFinish, 1);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2003-2011 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2003-2016 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -229,15 +229,18 @@ unsigned is_string_obj(vpiHandle obj)
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find the enclosing module.
|
* Find the enclosing module. If there is no enclosing module (which can be
|
||||||
|
* the case in SystemVerilog), return the highest enclosing scope.
|
||||||
*/
|
*/
|
||||||
vpiHandle sys_func_module(vpiHandle obj)
|
vpiHandle sys_func_module(vpiHandle obj)
|
||||||
{
|
{
|
||||||
assert(obj);
|
assert(obj);
|
||||||
|
|
||||||
while (vpi_get(vpiType, obj) != vpiModule) {
|
while (vpi_get(vpiType, obj) != vpiModule) {
|
||||||
obj = vpi_handle(vpiScope, obj);
|
vpiHandle scope = vpi_handle(vpiScope, obj);
|
||||||
assert(obj);
|
if (scope == 0)
|
||||||
|
break;
|
||||||
|
obj = scope;
|
||||||
}
|
}
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
|
|
|
||||||
39
vvp/arith.cc
39
vvp/arith.cc
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2013 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2001-2016 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -26,13 +26,13 @@
|
||||||
# include <cmath>
|
# include <cmath>
|
||||||
|
|
||||||
vvp_arith_::vvp_arith_(unsigned wid)
|
vvp_arith_::vvp_arith_(unsigned wid)
|
||||||
: wid_(wid), x_val_(wid)
|
: wid_(wid), op_a_(wid), op_b_(wid), x_val_(wid)
|
||||||
{
|
{
|
||||||
for (unsigned idx = 0 ; idx < wid ; idx += 1)
|
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
|
||||||
|
op_a_ .set_bit(idx, BIT4_Z);
|
||||||
|
op_b_ .set_bit(idx, BIT4_Z);
|
||||||
x_val_.set_bit(idx, BIT4_X);
|
x_val_.set_bit(idx, BIT4_X);
|
||||||
|
}
|
||||||
op_a_ = x_val_;
|
|
||||||
op_b_ = x_val_;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void vvp_arith_::dispatch_operand_(vvp_net_ptr_t ptr, vvp_vector4_t bit)
|
void vvp_arith_::dispatch_operand_(vvp_net_ptr_t ptr, vvp_vector4_t bit)
|
||||||
|
|
@ -51,6 +51,12 @@ void vvp_arith_::dispatch_operand_(vvp_net_ptr_t ptr, vvp_vector4_t bit)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void vvp_arith_::recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||||
|
unsigned base, unsigned wid, unsigned vwid,
|
||||||
|
vvp_context_t ctx)
|
||||||
|
{
|
||||||
|
recv_vec4_pv_(ptr, bit, base, wid, vwid, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
vvp_arith_abs::vvp_arith_abs()
|
vvp_arith_abs::vvp_arith_abs()
|
||||||
{
|
{
|
||||||
|
|
@ -82,6 +88,13 @@ void vvp_arith_abs::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||||
ptr.ptr()->send_vec4(out, 0);
|
ptr.ptr()->send_vec4(out, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void vvp_arith_abs::recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||||
|
unsigned base, unsigned wid, unsigned vwid,
|
||||||
|
vvp_context_t ctx)
|
||||||
|
{
|
||||||
|
recv_vec4_pv_(ptr, bit, base, wid, vwid, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
void vvp_arith_abs::recv_real(vvp_net_ptr_t ptr, double bit,
|
void vvp_arith_abs::recv_real(vvp_net_ptr_t ptr, double bit,
|
||||||
vvp_context_t)
|
vvp_context_t)
|
||||||
{
|
{
|
||||||
|
|
@ -121,6 +134,13 @@ void vvp_arith_cast_real::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||||
ptr.ptr()->send_real(val, 0);
|
ptr.ptr()->send_real(val, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void vvp_arith_cast_real::recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||||
|
unsigned base, unsigned wid, unsigned vwid,
|
||||||
|
vvp_context_t ctx)
|
||||||
|
{
|
||||||
|
recv_vec4_pv_(ptr, bit, base, wid, vwid, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
vvp_arith_cast_vec2::vvp_arith_cast_vec2(unsigned wid)
|
vvp_arith_cast_vec2::vvp_arith_cast_vec2(unsigned wid)
|
||||||
: wid_(wid)
|
: wid_(wid)
|
||||||
{
|
{
|
||||||
|
|
@ -143,6 +163,13 @@ void vvp_arith_cast_vec2::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||||
ptr.ptr()->send_vec4(vector2_to_vector4(tmp,wid_), 0);
|
ptr.ptr()->send_vec4(vector2_to_vector4(tmp,wid_), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void vvp_arith_cast_vec2::recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||||
|
unsigned base, unsigned wid, unsigned vwid,
|
||||||
|
vvp_context_t ctx)
|
||||||
|
{
|
||||||
|
recv_vec4_pv_(ptr, bit, base, wid, vwid, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
// Division
|
// Division
|
||||||
|
|
||||||
vvp_arith_div::vvp_arith_div(unsigned wid, bool signed_flag)
|
vvp_arith_div::vvp_arith_div(unsigned wid, bool signed_flag)
|
||||||
|
|
|
||||||
18
vvp/arith.h
18
vvp/arith.h
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef IVL_arith_H
|
#ifndef IVL_arith_H
|
||||||
#define IVL_arith_H
|
#define IVL_arith_H
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2014 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2001-2016 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -37,6 +37,10 @@ class vvp_arith_ : public vvp_net_fun_t {
|
||||||
public:
|
public:
|
||||||
explicit vvp_arith_(unsigned wid);
|
explicit vvp_arith_(unsigned wid);
|
||||||
|
|
||||||
|
void recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||||
|
unsigned base, unsigned wid, unsigned vwid,
|
||||||
|
vvp_context_t ctx);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void dispatch_operand_(vvp_net_ptr_t ptr, vvp_vector4_t bit);
|
void dispatch_operand_(vvp_net_ptr_t ptr, vvp_vector4_t bit);
|
||||||
|
|
||||||
|
|
@ -59,6 +63,10 @@ class vvp_arith_abs : public vvp_net_fun_t {
|
||||||
void recv_real(vvp_net_ptr_t ptr, double bit,
|
void recv_real(vvp_net_ptr_t ptr, double bit,
|
||||||
vvp_context_t);
|
vvp_context_t);
|
||||||
|
|
||||||
|
void recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||||
|
unsigned base, unsigned wid, unsigned vwid,
|
||||||
|
vvp_context_t ctx);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -82,6 +90,10 @@ class vvp_arith_cast_real : public vvp_net_fun_t {
|
||||||
void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||||
vvp_context_t);
|
vvp_context_t);
|
||||||
|
|
||||||
|
void recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||||
|
unsigned base, unsigned wid, unsigned vwid,
|
||||||
|
vvp_context_t ctx);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool signed_;
|
bool signed_;
|
||||||
};
|
};
|
||||||
|
|
@ -96,6 +108,10 @@ class vvp_arith_cast_vec2 : public vvp_net_fun_t {
|
||||||
void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||||
vvp_context_t);
|
vvp_context_t);
|
||||||
|
|
||||||
|
void recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||||
|
unsigned base, unsigned wid, unsigned vwid,
|
||||||
|
vvp_context_t ctx);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
unsigned wid_;
|
unsigned wid_;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2010 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2001-2016 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -81,3 +81,10 @@ void vvp_fun_bufif::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||||
|
|
||||||
ptr.ptr()->send_vec8(out);
|
ptr.ptr()->send_vec8(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void vvp_fun_bufif::recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||||
|
unsigned base, unsigned wid, unsigned vwid,
|
||||||
|
vvp_context_t ctx)
|
||||||
|
{
|
||||||
|
recv_vec4_pv_(ptr, bit, base, wid, vwid, ctx);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef IVL_bufif_H
|
#ifndef IVL_bufif_H
|
||||||
#define IVL_bufif_H
|
#define IVL_bufif_H
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2014 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2001-2016 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -40,6 +40,10 @@ class vvp_fun_bufif : public vvp_net_fun_t {
|
||||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||||
vvp_context_t);
|
vvp_context_t);
|
||||||
|
|
||||||
|
void recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||||
|
unsigned base, unsigned wid, unsigned vwid,
|
||||||
|
vvp_context_t ctx);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
vvp_vector4_t bit_;
|
vvp_vector4_t bit_;
|
||||||
vvp_vector4_t en_;
|
vvp_vector4_t en_;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2014 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2001-2016 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -1935,7 +1935,9 @@ void compile_thread(char*start_sym, char*flag)
|
||||||
|
|
||||||
vthread_t thr = vthread_new(pc, vpip_peek_current_scope());
|
vthread_t thr = vthread_new(pc, vpip_peek_current_scope());
|
||||||
|
|
||||||
if (flag && (strcmp(flag,"$final") == 0))
|
if (flag && (strcmp(flag,"$init") == 0))
|
||||||
|
schedule_init_vthread(thr);
|
||||||
|
else if (flag && (strcmp(flag,"$final") == 0))
|
||||||
schedule_final_vthread(thr);
|
schedule_final_vthread(thr);
|
||||||
else
|
else
|
||||||
schedule_vthread(thr, 0, push_flag);
|
schedule_vthread(thr, 0, push_flag);
|
||||||
|
|
|
||||||
15
vvp/delay.cc
15
vvp/delay.cc
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2005-2014 Stephen Williams <steve@icarus.com>
|
* Copyright (c) 2005-2016 Stephen Williams <steve@icarus.com>
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -332,6 +332,13 @@ void vvp_fun_delay::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void vvp_fun_delay::recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||||
|
unsigned base, unsigned wid, unsigned vwid,
|
||||||
|
vvp_context_t ctx)
|
||||||
|
{
|
||||||
|
recv_vec4_pv_(ptr, bit, base, wid, vwid, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
/* See the recv_vec4 comment above. */
|
/* See the recv_vec4 comment above. */
|
||||||
void vvp_fun_delay::recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit)
|
void vvp_fun_delay::recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit)
|
||||||
{
|
{
|
||||||
|
|
@ -397,6 +404,12 @@ void vvp_fun_delay::recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void vvp_fun_delay::recv_vec8_pv(vvp_net_ptr_t ptr, const vvp_vector8_t&bit,
|
||||||
|
unsigned base, unsigned wid, unsigned vwid)
|
||||||
|
{
|
||||||
|
recv_vec8_pv_(ptr, bit, base, wid, vwid);
|
||||||
|
}
|
||||||
|
|
||||||
void vvp_fun_delay::recv_real(vvp_net_ptr_t port, double bit,
|
void vvp_fun_delay::recv_real(vvp_net_ptr_t port, double bit,
|
||||||
vvp_context_t)
|
vvp_context_t)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef IVL_delay_H
|
#ifndef IVL_delay_H
|
||||||
#define IVL_delay_H
|
#define IVL_delay_H
|
||||||
/*
|
/*
|
||||||
* Copyright 2005-2014 Stephen Williams
|
* Copyright 2005-2016 Stephen Williams
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -99,6 +99,12 @@ class vvp_fun_delay : public vvp_net_fun_t, private vvp_gen_event_s {
|
||||||
vvp_context_t);
|
vvp_context_t);
|
||||||
//void recv_long(vvp_net_ptr_t port, long bit);
|
//void recv_long(vvp_net_ptr_t port, long bit);
|
||||||
|
|
||||||
|
void recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||||
|
unsigned base, unsigned wid, unsigned vwid,
|
||||||
|
vvp_context_t ctx);
|
||||||
|
void recv_vec8_pv(vvp_net_ptr_t ptr, const vvp_vector8_t&bit,
|
||||||
|
unsigned base, unsigned wid, unsigned vwid);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual void run_run();
|
virtual void run_run();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2005-2015 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2005-2016 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -103,6 +103,13 @@ void vvp_dff::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void vvp_dff::recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||||
|
unsigned base, unsigned wid, unsigned vwid,
|
||||||
|
vvp_context_t ctx)
|
||||||
|
{
|
||||||
|
recv_vec4_pv_(ptr, bit, base, wid, vwid, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The recv_async functions respond to the asynchronous
|
* The recv_async functions respond to the asynchronous
|
||||||
* set/clear input by propagating the desired output.
|
* set/clear input by propagating the desired output.
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef IVL_dff_H
|
#ifndef IVL_dff_H
|
||||||
#define IVL_dff_H
|
#define IVL_dff_H
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2005-2015 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2005-2016 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -44,6 +44,10 @@ class vvp_dff : public vvp_net_fun_t {
|
||||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||||
vvp_context_t);
|
vvp_context_t);
|
||||||
|
|
||||||
|
void recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||||
|
unsigned base, unsigned wid, unsigned vwid,
|
||||||
|
vvp_context_t ctx);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual void recv_async(vvp_net_ptr_t port);
|
virtual void recv_async(vvp_net_ptr_t port);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2005-2010 Stephen Williams <steve@icarus.com>
|
* Copyright (c) 2005-2016 Stephen Williams <steve@icarus.com>
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -51,3 +51,10 @@ void vvp_fun_extend_signed::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bi
|
||||||
|
|
||||||
port.ptr()->send_vec4(res, 0);
|
port.ptr()->send_vec4(res, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void vvp_fun_extend_signed::recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||||
|
unsigned base, unsigned wid, unsigned vwid,
|
||||||
|
vvp_context_t ctx)
|
||||||
|
{
|
||||||
|
recv_vec4_pv_(ptr, bit, base, wid, vwid, ctx);
|
||||||
|
}
|
||||||
|
|
|
||||||
28
vvp/npmos.cc
28
vvp/npmos.cc
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2005 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2005-2016 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -43,6 +43,19 @@ void vvp_fun_pmos_::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||||
generate_output_(ptr);
|
generate_output_(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void vvp_fun_pmos_::recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||||
|
unsigned base, unsigned wid, unsigned vwid,
|
||||||
|
vvp_context_t ctx)
|
||||||
|
{
|
||||||
|
recv_vec4_pv_(ptr, bit, base, wid, vwid, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void vvp_fun_pmos_::recv_vec8_pv(vvp_net_ptr_t ptr, const vvp_vector8_t&bit,
|
||||||
|
unsigned base, unsigned wid, unsigned vwid)
|
||||||
|
{
|
||||||
|
recv_vec8_pv_(ptr, bit, base, wid, vwid);
|
||||||
|
}
|
||||||
|
|
||||||
void vvp_fun_pmos_::generate_output_(vvp_net_ptr_t ptr)
|
void vvp_fun_pmos_::generate_output_(vvp_net_ptr_t ptr)
|
||||||
{
|
{
|
||||||
vvp_vector8_t out (bit_.size());
|
vvp_vector8_t out (bit_.size());
|
||||||
|
|
@ -147,7 +160,18 @@ void vvp_fun_cmos_::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t &bit,
|
||||||
generate_output_(ptr);
|
generate_output_(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <iostream>
|
void vvp_fun_cmos_::recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||||
|
unsigned base, unsigned wid, unsigned vwid,
|
||||||
|
vvp_context_t ctx)
|
||||||
|
{
|
||||||
|
recv_vec4_pv_(ptr, bit, base, wid, vwid, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void vvp_fun_cmos_::recv_vec8_pv(vvp_net_ptr_t ptr, const vvp_vector8_t&bit,
|
||||||
|
unsigned base, unsigned wid, unsigned vwid)
|
||||||
|
{
|
||||||
|
recv_vec8_pv_(ptr, bit, base, wid, vwid);
|
||||||
|
}
|
||||||
|
|
||||||
void vvp_fun_cmos_::generate_output_(vvp_net_ptr_t ptr)
|
void vvp_fun_cmos_::generate_output_(vvp_net_ptr_t ptr)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
14
vvp/npmos.h
14
vvp/npmos.h
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef IVL_npmos_H
|
#ifndef IVL_npmos_H
|
||||||
#define IVL_npmos_H
|
#define IVL_npmos_H
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2005-2014 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2005-2016 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -51,6 +51,12 @@ class vvp_fun_pmos_ : public vvp_net_fun_t {
|
||||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||||
vvp_context_t);
|
vvp_context_t);
|
||||||
|
|
||||||
|
void recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||||
|
unsigned base, unsigned wid, unsigned vwid,
|
||||||
|
vvp_context_t ctx);
|
||||||
|
void recv_vec8_pv(vvp_net_ptr_t ptr, const vvp_vector8_t&bit,
|
||||||
|
unsigned base, unsigned wid, unsigned vwid);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void generate_output_(vvp_net_ptr_t port);
|
void generate_output_(vvp_net_ptr_t port);
|
||||||
|
|
||||||
|
|
@ -108,6 +114,12 @@ class vvp_fun_cmos_ : public vvp_net_fun_t {
|
||||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t &bit,
|
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t &bit,
|
||||||
vvp_context_t);
|
vvp_context_t);
|
||||||
|
|
||||||
|
void recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||||
|
unsigned base, unsigned wid, unsigned vwid,
|
||||||
|
vvp_context_t ctx);
|
||||||
|
void recv_vec8_pv(vvp_net_ptr_t ptr, const vvp_vector8_t&bit,
|
||||||
|
unsigned base, unsigned wid, unsigned vwid);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void generate_output_(vvp_net_ptr_t port);
|
void generate_output_(vvp_net_ptr_t port);
|
||||||
|
|
||||||
|
|
|
||||||
17
vvp/part.cc
17
vvp/part.cc
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2004-2014 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2004-2016 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -208,6 +208,21 @@ void vvp_fun_part_pv::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||||
port.ptr()->send_vec4_pv(bit, base_, wid_, vwid_, context);
|
port.ptr()->send_vec4_pv(bit, base_, wid_, vwid_, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void vvp_fun_part_pv::recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||||
|
unsigned base, unsigned wid, unsigned vwid,
|
||||||
|
vvp_context_t ctx)
|
||||||
|
{
|
||||||
|
assert(port.port() == 0);
|
||||||
|
assert(bit.size() == wid);
|
||||||
|
assert(base + wid <= vwid);
|
||||||
|
assert(vwid == wid_);
|
||||||
|
|
||||||
|
vvp_vector4_t tmp(wid_, BIT4_Z);
|
||||||
|
tmp.set_vec(base, bit);
|
||||||
|
|
||||||
|
port.ptr()->send_vec4_pv(tmp, base_, wid_, vwid_, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
void vvp_fun_part_pv::recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit)
|
void vvp_fun_part_pv::recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit)
|
||||||
{
|
{
|
||||||
assert(port.port() == 0);
|
assert(port.port() == 0);
|
||||||
|
|
|
||||||
|
|
@ -109,6 +109,10 @@ class vvp_fun_part_pv : public vvp_net_fun_t {
|
||||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||||
vvp_context_t context);
|
vvp_context_t context);
|
||||||
|
|
||||||
|
void recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||||
|
unsigned, unsigned, unsigned,
|
||||||
|
vvp_context_t);
|
||||||
|
|
||||||
void recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit);
|
void recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2013 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2001-2016 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -760,6 +760,16 @@ void schedule_vthread(vthread_t thr, vvp_time64_t delay, bool push_flag)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void schedule_init_vthread(vthread_t thr)
|
||||||
|
{
|
||||||
|
struct vthread_event_s*cur = new vthread_event_s;
|
||||||
|
|
||||||
|
cur->thr = thr;
|
||||||
|
vthread_mark_scheduled(thr);
|
||||||
|
|
||||||
|
schedule_init_event(cur);
|
||||||
|
}
|
||||||
|
|
||||||
void schedule_final_vthread(vthread_t thr)
|
void schedule_final_vthread(vthread_t thr)
|
||||||
{
|
{
|
||||||
struct vthread_event_s*cur = new vthread_event_s;
|
struct vthread_event_s*cur = new vthread_event_s;
|
||||||
|
|
@ -939,6 +949,10 @@ extern void vpiStartOfSim();
|
||||||
extern void vpiPostsim();
|
extern void vpiPostsim();
|
||||||
extern void vpiNextSimTime(void);
|
extern void vpiNextSimTime(void);
|
||||||
|
|
||||||
|
static bool sim_at_rosync = false;
|
||||||
|
bool schedule_at_rosync(void)
|
||||||
|
{ return sim_at_rosync; }
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The scheduler uses this function to drain the rosync events of the
|
* The scheduler uses this function to drain the rosync events of the
|
||||||
* current time. The ctim object is still in the event queue, because
|
* current time. The ctim object is still in the event queue, because
|
||||||
|
|
@ -951,6 +965,7 @@ extern void vpiNextSimTime(void);
|
||||||
*/
|
*/
|
||||||
static void run_rosync(struct event_time_s*ctim)
|
static void run_rosync(struct event_time_s*ctim)
|
||||||
{
|
{
|
||||||
|
sim_at_rosync = true;
|
||||||
while (ctim->rosync) {
|
while (ctim->rosync) {
|
||||||
struct event_s*cur = ctim->rosync->next;
|
struct event_s*cur = ctim->rosync->next;
|
||||||
if (cur->next == cur) {
|
if (cur->next == cur) {
|
||||||
|
|
@ -962,6 +977,7 @@ static void run_rosync(struct event_time_s*ctim)
|
||||||
cur->run_run();
|
cur->run_run();
|
||||||
delete cur;
|
delete cur;
|
||||||
}
|
}
|
||||||
|
sim_at_rosync = false;
|
||||||
|
|
||||||
while (ctim->del_thr) {
|
while (ctim->del_thr) {
|
||||||
struct event_s*cur = ctim->del_thr->next;
|
struct event_s*cur = ctim->del_thr->next;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef IVL_schedule_H
|
#ifndef IVL_schedule_H
|
||||||
#define IVL_schedule_H
|
#define IVL_schedule_H
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2014 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2001-2016 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -35,6 +35,8 @@
|
||||||
extern void schedule_vthread(vthread_t thr, vvp_time64_t delay,
|
extern void schedule_vthread(vthread_t thr, vvp_time64_t delay,
|
||||||
bool push_flag =false);
|
bool push_flag =false);
|
||||||
|
|
||||||
|
extern void schedule_init_vthread(vthread_t thr);
|
||||||
|
|
||||||
extern void schedule_final_vthread(vthread_t thr);
|
extern void schedule_final_vthread(vthread_t thr);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -153,6 +155,13 @@ extern void schedule_simulate(void);
|
||||||
*/
|
*/
|
||||||
extern vvp_time64_t schedule_simtime(void);
|
extern vvp_time64_t schedule_simtime(void);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Indicate that the simulator is running the rosync callbacks. This is
|
||||||
|
* used to prevent the callbacks from performing any write operations
|
||||||
|
* in the current simulation time slot.
|
||||||
|
*/
|
||||||
|
extern bool schedule_at_rosync(void);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function is the equivalent of the $finish system task. It
|
* This function is the equivalent of the $finish system task. It
|
||||||
* tells the simulator that simulation is done, the current thread
|
* tells the simulator that simulation is done, the current thread
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2014 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2016 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -32,6 +32,10 @@ class vvp_fun_substitute : public vvp_net_fun_t {
|
||||||
|
|
||||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit, vvp_context_t);
|
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit, vvp_context_t);
|
||||||
|
|
||||||
|
void recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||||
|
unsigned base, unsigned wid, unsigned vwid,
|
||||||
|
vvp_context_t ctx);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
unsigned wid_;
|
unsigned wid_;
|
||||||
unsigned soff_;
|
unsigned soff_;
|
||||||
|
|
@ -77,6 +81,13 @@ void vvp_fun_substitute::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||||
port.ptr()->send_vec4(val_, 0);
|
port.ptr()->send_vec4(val_, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void vvp_fun_substitute::recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||||
|
unsigned base, unsigned wid, unsigned vwid,
|
||||||
|
vvp_context_t ctx)
|
||||||
|
{
|
||||||
|
recv_vec4_pv_(ptr, bit, base, wid, vwid, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
void compile_substitute(char*label, unsigned width,
|
void compile_substitute(char*label, unsigned width,
|
||||||
unsigned soff, unsigned swidth,
|
unsigned soff, unsigned swidth,
|
||||||
unsigned argc, struct symb_s*argv)
|
unsigned argc, struct symb_s*argv)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008-2015 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2008-2016 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -1068,9 +1068,9 @@ vpiHandle vpi_put_value(vpiHandle obj, s_vpi_value*vp,
|
||||||
int scale;
|
int scale;
|
||||||
|
|
||||||
if (vpi_get(vpiAutomatic, obj)) {
|
if (vpi_get(vpiAutomatic, obj)) {
|
||||||
fprintf(stderr, "vpi error: cannot put a value with "
|
fprintf(stderr, "VPI error: cannot put a value with "
|
||||||
"a delay on automatically allocated "
|
"a delay on automatically allocated "
|
||||||
"variable '%s'\n",
|
"variable '%s'.\n",
|
||||||
vpi_get_str(vpiName, obj));
|
vpi_get_str(vpiName, obj));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -1095,6 +1095,13 @@ vpiHandle vpi_put_value(vpiHandle obj, s_vpi_value*vp,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((dly == 0) && schedule_at_rosync()) {
|
||||||
|
fprintf(stderr, "VPI error: attempted to put a value to "
|
||||||
|
"variable '%s' during a read-only synch "
|
||||||
|
"callback.\n", vpi_get_str(vpiName, obj));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
vpip_put_value_event*put = new vpip_put_value_event;
|
vpip_put_value_event*put = new vpip_put_value_event;
|
||||||
put->handle = obj;
|
put->handle = obj;
|
||||||
put->value = *vp;
|
put->value = *vp;
|
||||||
|
|
@ -1132,6 +1139,13 @@ vpiHandle vpi_put_value(vpiHandle obj, s_vpi_value*vp,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (schedule_at_rosync()) {
|
||||||
|
fprintf(stderr, "VPI error: attempted to put a value to "
|
||||||
|
"variable '%s' during a read-only synch "
|
||||||
|
"callback.\n", vpi_get_str(vpiName, obj));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
obj->vpi_put_value(vp, flags);
|
obj->vpi_put_value(vp, flags);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2015 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2001-2016 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -1409,6 +1409,9 @@ static vpiHandle PV_get_handle(int code, vpiHandle ref)
|
||||||
case vpiParent:
|
case vpiParent:
|
||||||
return rfp->parent;
|
return rfp->parent;
|
||||||
|
|
||||||
|
case vpiScope:
|
||||||
|
return vpi_handle(vpiScope, rfp->parent);
|
||||||
|
|
||||||
case vpiModule:
|
case vpiModule:
|
||||||
return vpi_handle(vpiModule, rfp->parent);
|
return vpi_handle(vpiModule, rfp->parent);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3249,6 +3249,31 @@ void vvp_net_fun_t::recv_vec4(vvp_net_ptr_t, const vvp_vector4_t&,
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void vvp_net_fun_t::recv_vec4_pv_(vvp_net_ptr_t p, const vvp_vector4_t&bit,
|
||||||
|
unsigned base, unsigned wid, unsigned vwid,
|
||||||
|
vvp_context_t)
|
||||||
|
{
|
||||||
|
// The majority of functors don't normally expect to receive part
|
||||||
|
// values, because the primary operands of an expression will be
|
||||||
|
// extended to the expression width. But in the case that a primary
|
||||||
|
// operand is a wire that is only partly driven by a single driver,
|
||||||
|
// the part value driven onto the wire propagates directly to the
|
||||||
|
// inputs of any functors connected to that wire. In this case we
|
||||||
|
// know that the remaining bits are undriven, so can simply build
|
||||||
|
// the full width value from the part we have received.
|
||||||
|
//
|
||||||
|
// Note that this case is almost certainly a bug in the user's
|
||||||
|
// code, but we still need to handle it correctly. See GitHub
|
||||||
|
// issue #99 and br_gh99*.v in the test suite for examples.
|
||||||
|
|
||||||
|
assert(bit.size() == wid);
|
||||||
|
assert(base + wid <= vwid);
|
||||||
|
|
||||||
|
vvp_vector4_t tmp(vwid, BIT4_Z);
|
||||||
|
tmp.set_vec(base, bit);
|
||||||
|
recv_vec4(p, tmp, 0);
|
||||||
|
}
|
||||||
|
|
||||||
void vvp_net_fun_t::recv_vec4_pv(vvp_net_ptr_t, const vvp_vector4_t&bit,
|
void vvp_net_fun_t::recv_vec4_pv(vvp_net_ptr_t, const vvp_vector4_t&bit,
|
||||||
unsigned base, unsigned wid, unsigned vwid,
|
unsigned base, unsigned wid, unsigned vwid,
|
||||||
vvp_context_t)
|
vvp_context_t)
|
||||||
|
|
@ -3264,6 +3289,19 @@ void vvp_net_fun_t::recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit)
|
||||||
recv_vec4(port, reduce4(bit), 0);
|
recv_vec4(port, reduce4(bit), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void vvp_net_fun_t::recv_vec8_pv_(vvp_net_ptr_t p, const vvp_vector8_t&bit,
|
||||||
|
unsigned base, unsigned wid, unsigned vwid)
|
||||||
|
{
|
||||||
|
// This is the strength-aware version of recv_vec4_pv_.
|
||||||
|
|
||||||
|
assert(bit.size() == wid);
|
||||||
|
assert(base + wid <= vwid);
|
||||||
|
|
||||||
|
vvp_vector8_t tmp(vwid);
|
||||||
|
tmp.set_vec(base, bit);
|
||||||
|
recv_vec8(p, tmp);
|
||||||
|
}
|
||||||
|
|
||||||
void vvp_net_fun_t::recv_vec8_pv(vvp_net_ptr_t port, const vvp_vector8_t&bit,
|
void vvp_net_fun_t::recv_vec8_pv(vvp_net_ptr_t port, const vvp_vector8_t&bit,
|
||||||
unsigned base, unsigned wid, unsigned vwid)
|
unsigned base, unsigned wid, unsigned vwid)
|
||||||
{
|
{
|
||||||
|
|
@ -3331,6 +3369,12 @@ void vvp_fun_drive::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||||
port.ptr()->send_vec8(vvp_vector8_t(bit, drive0_, drive1_));
|
port.ptr()->send_vec8(vvp_vector8_t(bit, drive0_, drive1_));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void vvp_fun_drive::recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||||
|
unsigned base, unsigned wid, unsigned vwid,
|
||||||
|
vvp_context_t ctx)
|
||||||
|
{
|
||||||
|
recv_vec4_pv_(ptr, bit, base, wid, vwid, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
/* **** vvp_wide_fun_* methods **** */
|
/* **** vvp_wide_fun_* methods **** */
|
||||||
|
|
||||||
|
|
@ -3426,6 +3470,13 @@ void vvp_wide_fun_t::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||||
core_->dispatch_vec4_from_input_(pidx, bit);
|
core_->dispatch_vec4_from_input_(pidx, bit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void vvp_wide_fun_t::recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
|
||||||
|
unsigned base, unsigned wid, unsigned vwid,
|
||||||
|
vvp_context_t ctx)
|
||||||
|
{
|
||||||
|
recv_vec4_pv_(ptr, bit, base, wid, vwid, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
void vvp_wide_fun_t::recv_real(vvp_net_ptr_t port, double bit,
|
void vvp_wide_fun_t::recv_real(vvp_net_ptr_t port, double bit,
|
||||||
vvp_context_t)
|
vvp_context_t)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef IVL_vvp_net_H
|
#ifndef IVL_vvp_net_H
|
||||||
#define IVL_vvp_net_H
|
#define IVL_vvp_net_H
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2004-2015 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 2004-2016 Stephen Williams (steve@icarus.com)
|
||||||
*
|
*
|
||||||
* This source code is free software; you can redistribute it
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -1230,6 +1230,13 @@ class vvp_net_fun_t {
|
||||||
// do something about it.
|
// do something about it.
|
||||||
virtual void force_flag(bool run_now);
|
virtual void force_flag(bool run_now);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void recv_vec4_pv_(vvp_net_ptr_t p, const vvp_vector4_t&bit,
|
||||||
|
unsigned base, unsigned wid, unsigned vwid,
|
||||||
|
vvp_context_t context);
|
||||||
|
void recv_vec8_pv_(vvp_net_ptr_t p, const vvp_vector8_t&bit,
|
||||||
|
unsigned base, unsigned wid, unsigned vwid);
|
||||||
|
|
||||||
public: // These objects are only permallocated.
|
public: // These objects are only permallocated.
|
||||||
static void* operator new(std::size_t size) { return heap_.alloc(size); }
|
static void* operator new(std::size_t size) { return heap_.alloc(size); }
|
||||||
static void operator delete(void*); // not implemented
|
static void operator delete(void*); // not implemented
|
||||||
|
|
@ -1470,6 +1477,9 @@ class vvp_fun_drive : public vvp_net_fun_t {
|
||||||
vvp_context_t context);
|
vvp_context_t context);
|
||||||
//void recv_long(vvp_net_ptr_t port, long bit);
|
//void recv_long(vvp_net_ptr_t port, long bit);
|
||||||
|
|
||||||
|
void recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||||
|
unsigned base, unsigned wid, unsigned vwid,
|
||||||
|
vvp_context_t);
|
||||||
private:
|
private:
|
||||||
unsigned char drive0_;
|
unsigned char drive0_;
|
||||||
unsigned char drive1_;
|
unsigned char drive1_;
|
||||||
|
|
@ -1490,6 +1500,9 @@ class vvp_fun_extend_signed : public vvp_net_fun_t {
|
||||||
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||||
vvp_context_t context);
|
vvp_context_t context);
|
||||||
|
|
||||||
|
void recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
||||||
|
unsigned base, unsigned wid, unsigned vwid,
|
||||||
|
vvp_context_t);
|
||||||
private:
|
private:
|
||||||
unsigned width_;
|
unsigned width_;
|
||||||
};
|
};
|
||||||
|
|
@ -1571,6 +1584,10 @@ class vvp_wide_fun_t : public vvp_net_fun_t {
|
||||||
void recv_real(vvp_net_ptr_t port, double bit,
|
void recv_real(vvp_net_ptr_t port, double bit,
|
||||||
vvp_context_t context);
|
vvp_context_t context);
|
||||||
|
|
||||||
|
void recv_vec4_pv(vvp_net_ptr_t p, const vvp_vector4_t&bit,
|
||||||
|
unsigned base, unsigned wid, unsigned vwid,
|
||||||
|
vvp_context_t context);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
vvp_wide_fun_core*core_;
|
vvp_wide_fun_core*core_;
|
||||||
unsigned port_base_;
|
unsigned port_base_;
|
||||||
|
|
|
||||||
|
|
@ -393,7 +393,7 @@ class vvp_fun_signal_object_aa : public vvp_fun_signal_object, public automatic_
|
||||||
/* vvp_wire
|
/* vvp_wire
|
||||||
* The vvp_wire is different from vvp_variable objects in that it
|
* The vvp_wire is different from vvp_variable objects in that it
|
||||||
* exists only as a filter. The vvp_wire class tree is for
|
* exists only as a filter. The vvp_wire class tree is for
|
||||||
* implementing verilog wires/nets (as opposed to regs/variables).
|
* implementing Verilog wires/nets (as opposed to regs/variables).
|
||||||
*
|
*
|
||||||
* vvp_vpi_callback
|
* vvp_vpi_callback
|
||||||
* |
|
* |
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue