Compare commits
111 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
3d14281e0d | |
|
|
2564554178 | |
|
|
8cd697fd24 | |
|
|
306d2fb53b | |
|
|
52b497f74c | |
|
|
ce7f28202a | |
|
|
49bea6a01a | |
|
|
8ab100c1c7 | |
|
|
177ae7c220 | |
|
|
b04d5a9068 | |
|
|
b8c8f03037 | |
|
|
38013f7a34 | |
|
|
561638a31f | |
|
|
bb91512e75 | |
|
|
09ff851483 | |
|
|
19d8f43e9b | |
|
|
ce88deaa97 | |
|
|
1a8b19baf2 | |
|
|
b3cf533b3c | |
|
|
ba3856ebb0 | |
|
|
c06e2790a7 | |
|
|
6e460a6a3f | |
|
|
dbc536c4fb | |
|
|
5e41c86d01 | |
|
|
572124e1e9 | |
|
|
37ecdb4cfb | |
|
|
a11dc8b472 | |
|
|
e7852f8f9c | |
|
|
9449c46865 | |
|
|
8a780ece56 | |
|
|
8bb4777789 | |
|
|
3b705d95a6 | |
|
|
f9559853f1 | |
|
|
cda95c1554 | |
|
|
4066031add | |
|
|
d6d50e9b68 | |
|
|
0ffbb2b1de | |
|
|
9b55a3d67f | |
|
|
07623bef2e | |
|
|
73d688c313 | |
|
|
6155986d1c | |
|
|
face462cc2 | |
|
|
a5f6329500 | |
|
|
3e13594816 | |
|
|
99138eafb1 | |
|
|
86968e3752 | |
|
|
27a46f4afe | |
|
|
d770199550 | |
|
|
06f6a72770 | |
|
|
30257e0914 | |
|
|
b2281b0e65 | |
|
|
161cebb178 | |
|
|
b46d8b8389 | |
|
|
2689ebacfe | |
|
|
5bbb054173 | |
|
|
7d2eeb0137 | |
|
|
4aef636559 | |
|
|
72fc3d712d | |
|
|
3f75f6b155 | |
|
|
9be3fc3a56 | |
|
|
aa2260f4fa | |
|
|
6974613bff | |
|
|
8bd4e9d481 | |
|
|
04ae07f03c | |
|
|
d9be5318f9 | |
|
|
88cd5534c4 | |
|
|
3b577340ad | |
|
|
583a31c121 | |
|
|
a391c3ae28 | |
|
|
b551a783e8 | |
|
|
33db07ab8d | |
|
|
e2aae72880 | |
|
|
ec9897af5a | |
|
|
2771abf86a | |
|
|
b0461787c8 | |
|
|
6f41576930 | |
|
|
cc7516eab3 | |
|
|
1a5ae96540 | |
|
|
1ea8a13bf8 | |
|
|
490884cf7b | |
|
|
ca1d7ccffe | |
|
|
faf9bfe158 | |
|
|
086ce04cf5 | |
|
|
7b7231c417 | |
|
|
d7b919f6d0 | |
|
|
9b34a96cb9 | |
|
|
90cf0e5794 | |
|
|
818379b9bc | |
|
|
9fbb7f84e6 | |
|
|
ed7d6c1002 | |
|
|
a4306dbac1 | |
|
|
a682e13d82 | |
|
|
643e0a984e | |
|
|
63d2059b85 | |
|
|
d9e09ceb59 | |
|
|
6d0ab9978f | |
|
|
e25cdf86ac | |
|
|
13bff8c50d | |
|
|
b1b017251a | |
|
|
e13a52637a | |
|
|
4803f0d12b | |
|
|
be44289fc0 | |
|
|
e682166253 | |
|
|
e2a1f21896 | |
|
|
cb73accd84 | |
|
|
a66361a4f2 | |
|
|
1159de0482 | |
|
|
ac5d4114ad | |
|
|
85f796fda2 | |
|
|
8612ec5452 | |
|
|
870a351944 |
2
HName.cc
2
HName.cc
|
|
@ -40,7 +40,7 @@ hname_t::hname_t(perm_string text, int num)
|
|||
number_[0] = num;
|
||||
}
|
||||
|
||||
hname_t::hname_t(perm_string text, vector<int>&nums)
|
||||
hname_t::hname_t(perm_string text, const vector<int>&nums)
|
||||
: name_(text), number_(nums)
|
||||
{
|
||||
}
|
||||
|
|
|
|||
13
HName.h
13
HName.h
|
|
@ -42,7 +42,7 @@ class hname_t {
|
|||
hname_t ();
|
||||
explicit hname_t (perm_string text);
|
||||
explicit hname_t (perm_string text, int num);
|
||||
explicit hname_t (perm_string text, std::vector<int>&nums);
|
||||
explicit hname_t (perm_string text, const std::vector<int>&nums);
|
||||
hname_t (const hname_t&that);
|
||||
~hname_t();
|
||||
|
||||
|
|
@ -56,12 +56,12 @@ class hname_t {
|
|||
|
||||
size_t has_numbers() const;
|
||||
int peek_number(size_t idx) const;
|
||||
const std::vector<int>&peek_numbers() const;
|
||||
|
||||
private:
|
||||
perm_string name_;
|
||||
// If the number is anything other than INT_MIN, then this is
|
||||
// the numeric part of the name. Otherwise, it is not part of
|
||||
// the name at all.
|
||||
// If this vector has size, then the numbers all together make
|
||||
// up part of the hierarchical name.
|
||||
std::vector<int> number_;
|
||||
|
||||
private: // not implemented
|
||||
|
|
@ -82,6 +82,11 @@ inline int hname_t::peek_number(size_t idx) const
|
|||
return number_[idx];
|
||||
}
|
||||
|
||||
inline const std::vector<int>& hname_t::peek_numbers(void) const
|
||||
{
|
||||
return number_;
|
||||
}
|
||||
|
||||
inline size_t hname_t::has_numbers() const
|
||||
{
|
||||
return number_.size();
|
||||
|
|
|
|||
|
|
@ -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
|
||||
* 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;
|
||||
uc_drive = UCD_NONE;
|
||||
timescale_warn_done = false;
|
||||
time_unit = 0;
|
||||
time_precision = 0;
|
||||
time_from_timescale = false;
|
||||
}
|
||||
|
||||
Module::~Module()
|
||||
|
|
|
|||
6
Module.h
6
Module.h
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef 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
|
||||
* 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;
|
||||
|
||||
/* 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;
|
||||
|
||||
/* 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)
|
||||
*
|
||||
* 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);
|
||||
}
|
||||
|
||||
PECastSize::PECastSize(unsigned si, PExpr*b)
|
||||
PECastSize::PECastSize(PExpr*si, PExpr*b)
|
||||
: size_(si), base_(b)
|
||||
{
|
||||
}
|
||||
|
|
|
|||
6
PExpr.h
6
PExpr.h
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef 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)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
|
|
@ -971,7 +971,7 @@ class PECallFunction : public PExpr {
|
|||
class PECastSize : public PExpr {
|
||||
|
||||
public:
|
||||
explicit PECastSize(unsigned expr_wid, PExpr*base);
|
||||
explicit PECastSize(PExpr*size, PExpr*base);
|
||||
~PECastSize();
|
||||
|
||||
void dump(ostream &out) const;
|
||||
|
|
@ -984,7 +984,7 @@ class PECastSize : public PExpr {
|
|||
width_mode_t&mode);
|
||||
|
||||
private:
|
||||
unsigned size_;
|
||||
PExpr* size_;
|
||||
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
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -19,21 +19,9 @@
|
|||
|
||||
# include "PScope.h"
|
||||
|
||||
PScope::PScope(perm_string n, LexicalScope*parent)
|
||||
: LexicalScope(parent), name_(n)
|
||||
bool LexicalScope::var_init_needs_explicit_lifetime() const
|
||||
{
|
||||
}
|
||||
|
||||
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;
|
||||
return false;
|
||||
}
|
||||
|
||||
PWire* LexicalScope::wires_find(perm_string name)
|
||||
|
|
@ -45,17 +33,26 @@ PWire* LexicalScope::wires_find(perm_string name)
|
|||
return (*cur).second;
|
||||
}
|
||||
|
||||
PScopeExtra::PScopeExtra(perm_string n, LexicalScope*parent)
|
||||
: PScope(n, parent)
|
||||
PScope::PScope(perm_string n, LexicalScope*parent)
|
||||
: LexicalScope(parent), name_(n)
|
||||
{
|
||||
time_unit = 0;
|
||||
time_precision = 0;
|
||||
time_from_timescale = false;
|
||||
}
|
||||
|
||||
PScopeExtra::PScopeExtra(perm_string n)
|
||||
: PScope(n)
|
||||
PScope::~PScope()
|
||||
{
|
||||
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()
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
32
PScope.h
32
PScope.h
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef 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
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -36,6 +36,7 @@ class PProcess;
|
|||
class PClass;
|
||||
class PTask;
|
||||
class PWire;
|
||||
class Statement;
|
||||
|
||||
class Design;
|
||||
class NetScope;
|
||||
|
|
@ -52,10 +53,14 @@ class NetScope;
|
|||
class LexicalScope {
|
||||
|
||||
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.
|
||||
virtual ~LexicalScope() { }
|
||||
|
||||
lifetime_t default_lifetime;
|
||||
|
||||
struct range_t {
|
||||
// True if this is an exclude
|
||||
bool exclude_flag;
|
||||
|
|
@ -108,6 +113,9 @@ class LexicalScope {
|
|||
// creating implicit nets.
|
||||
map<perm_string,LineInfo*> genvars;
|
||||
|
||||
// Variable initializations in this scope
|
||||
vector<Statement*> var_inits;
|
||||
|
||||
// Behaviors (processes) in this scope
|
||||
list<PProcess*> behaviors;
|
||||
list<AProcess*> analog_behaviors;
|
||||
|
|
@ -117,6 +125,8 @@ class LexicalScope {
|
|||
|
||||
LexicalScope* parent_scope() const { return parent_; }
|
||||
|
||||
virtual bool var_init_needs_explicit_lifetime() const;
|
||||
|
||||
protected:
|
||||
void dump_typedefs_(ostream&out, unsigned indent) const;
|
||||
|
||||
|
|
@ -130,6 +140,10 @@ class LexicalScope {
|
|||
|
||||
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:
|
||||
LexicalScope*parent_;
|
||||
};
|
||||
|
|
@ -145,12 +159,17 @@ class PScope : public LexicalScope {
|
|||
// modules do not nest in Verilog, the parent must be nil for
|
||||
// modules. Scopes for tasks and functions point to their
|
||||
// containing module.
|
||||
PScope(perm_string name, LexicalScope*parent);
|
||||
PScope(perm_string name);
|
||||
explicit PScope(perm_string name, LexicalScope*parent =0);
|
||||
virtual ~PScope();
|
||||
|
||||
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:
|
||||
bool elaborate_sig_wires_(Design*des, NetScope*scope) const;
|
||||
|
||||
|
|
@ -168,14 +187,13 @@ class PScope : public LexicalScope {
|
|||
class PScopeExtra : public PScope {
|
||||
|
||||
public:
|
||||
PScopeExtra(perm_string, LexicalScope*parent);
|
||||
PScopeExtra(perm_string);
|
||||
explicit PScopeExtra(perm_string, LexicalScope*parent =0);
|
||||
~PScopeExtra();
|
||||
|
||||
/* Task definitions within this module */
|
||||
std::map<perm_string,PTask*> tasks;
|
||||
std::map<perm_string,PFunction*> funcs;
|
||||
/* class definitions within this module. */
|
||||
/* Class definitions within this module. */
|
||||
std::map<perm_string,PClass*> classes;
|
||||
/* This is the lexical order of the classes, and is used by
|
||||
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)
|
||||
{
|
||||
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();
|
||||
|
||||
bool var_init_needs_explicit_lifetime() const;
|
||||
|
||||
void set_ports(std::vector<pform_tf_port_t>*p);
|
||||
|
||||
void set_this(class_type_t*use_type, PWire*this_wire);
|
||||
|
|
|
|||
|
|
@ -115,6 +115,11 @@ PBlock::~PBlock()
|
|||
delete list_[idx];
|
||||
}
|
||||
|
||||
bool PBlock::var_init_needs_explicit_lifetime() const
|
||||
{
|
||||
return default_lifetime == STATIC;
|
||||
}
|
||||
|
||||
PChainConstructor* PBlock::extract_chain_constructor()
|
||||
{
|
||||
if (list_.empty())
|
||||
|
|
|
|||
|
|
@ -108,7 +108,8 @@ class PAssign_ : public Statement {
|
|||
NetAssign_* elaborate_lval(Design*, NetScope*scope) const;
|
||||
NetExpr* elaborate_rval_(Design*, NetScope*, ivl_type_t lv_net_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_obj_(Design*, NetScope*,
|
||||
|
|
@ -182,6 +183,8 @@ class PBlock : public PScope, public Statement {
|
|||
|
||||
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
|
||||
// constructor. We look for a PChainConstructor as the first
|
||||
// statement, and if it is there, extract it.
|
||||
|
|
|
|||
34
compiler.h
34
compiler.h
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef 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
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -80,6 +80,10 @@ extern unsigned recursive_mod_limit;
|
|||
/* Implicit definitions of wires. */
|
||||
extern bool warn_implicit;
|
||||
|
||||
/* Warn if dimensions of port or var/net are implicitly taken from
|
||||
the input/output/inout declaration. */
|
||||
extern bool warn_implicit_dimensions;
|
||||
|
||||
/* inherit timescales across files. */
|
||||
extern bool warn_timescale;
|
||||
|
||||
|
|
@ -138,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
|
||||
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 {
|
||||
GN_VER1995 = 1,
|
||||
GN_VER2001_NOCONFIG = 2,
|
||||
|
|
@ -182,25 +187,24 @@ extern bool gn_strict_ca_eval_flag;
|
|||
standard expression width rules. */
|
||||
extern bool gn_strict_expr_width_flag;
|
||||
|
||||
/* 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 this flag is true, then don't add a for-loop control variable
|
||||
to an implicit event_expression list if it is only used inside the
|
||||
loop. */
|
||||
extern bool gn_shared_loop_index_flag;
|
||||
|
||||
static inline bool gn_system_verilog(void)
|
||||
{
|
||||
if (generation_flag == GN_VER2005_SV ||
|
||||
generation_flag == GN_VER2009 ||
|
||||
generation_flag == GN_VER2012)
|
||||
if (generation_flag >= GN_VER2005_SV)
|
||||
return true;
|
||||
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 ||
|
||||
generation_flag == GN_VER2009 ||
|
||||
generation_flag == GN_VER2012)
|
||||
return true;
|
||||
return false;
|
||||
return gn_system_verilog();
|
||||
}
|
||||
|
||||
static inline bool gn_modules_nest(void)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef IVL_config_H /* -*- c++ -*- */
|
||||
#define IVL_config_H
|
||||
/*
|
||||
* Copyright (c) 2001-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2001-2015 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
|
||||
|
|
@ -55,6 +55,7 @@
|
|||
# undef HAVE_FSEEKO
|
||||
/* And this is needed by the fst files (copied from GTKWave). */
|
||||
# undef HAVE_LIBPTHREAD
|
||||
# undef HAVE_REALPATH
|
||||
|
||||
/*
|
||||
* Define this if you want to compile vvp with memory freeing and
|
||||
|
|
|
|||
|
|
@ -242,6 +242,9 @@ case "${host}" in
|
|||
esac
|
||||
AC_SUBST(file64_support)
|
||||
|
||||
# fstapi.c (from GTKWave) needs this define.
|
||||
AC_CHECK_FUNCS(realpath)
|
||||
|
||||
# Check that these functions exist. They are mostly C99
|
||||
# functions that older compilers may not yet support.
|
||||
AC_CHECK_FUNCS(fopen64)
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ config.h: $(srcdir)/config.h.in Makefile
|
|||
|
||||
# Windows specific...
|
||||
res.rc: $(srcdir)/res.rc.in ../version.exe
|
||||
sed -e 's;@PRODUCTVERSION@;'`../version.exe '%M,%m,%n,0'`';' \
|
||||
sed -e 's;@PRODUCTVERSION@;'`../version.exe '%M,%n,0,0'`';' \
|
||||
$(srcdir)/res.rc.in > $@
|
||||
|
||||
res.o: res.rc
|
||||
|
|
|
|||
|
|
@ -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
|
||||
* 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; }
|
||||
"-f" { return TOK_Dc; }
|
||||
|
||||
/* Notice the -v flag. */
|
||||
/* Notice the -l or -v flag. */
|
||||
"-l" { return TOK_Dv; }
|
||||
"-v" { return TOK_Dv; }
|
||||
|
||||
/* Notice the -y flag. */
|
||||
|
|
|
|||
|
|
@ -1,14 +1,15 @@
|
|||
.TH iverilog 1 "Aug 7th, 2015" "" "Version %M.%m.%n %E"
|
||||
.TH iverilog 1 "Oct 2nd, 2016" "" "Version %M.%n%E"
|
||||
.SH NAME
|
||||
iverilog - Icarus Verilog compiler
|
||||
|
||||
.SH SYNOPSIS
|
||||
.B iverilog
|
||||
[\-ESVv] [\-Bpath] [\-ccmdfile|\-fcmdfile] [\-Dmacro[=defn]]
|
||||
[\-Pparameter=value] [\-pflag=value]
|
||||
[\-dname] [\-g1995|\-g2001|\-g2005|\-g2005-sv|\-g2009|\-g2012|\-g<feature>]
|
||||
[\-Pparameter=value] [\-pflag=value] [\-dname]
|
||||
[\-g1995\:|\-g2001\:|\-g2005\:|\-g2005-sv\:|\-g2009\:|\-g2012\:|\-g<feature>]
|
||||
[\-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
|
||||
.PP
|
||||
|
|
@ -30,7 +31,7 @@ different set of programs. The path given is used to locate
|
|||
\fIivlpp\fP, \fIivl\fP, code generators and the VPI modules.
|
||||
.TP 8
|
||||
.B -c\fIfile\fP -f\fIfile\fP
|
||||
These flags specifies an input file that contains a list of Verilog
|
||||
These flags specify an input file that contains a list of Verilog
|
||||
source files. This is similar to the \fIcommand file\fP of other
|
||||
Verilog simulators, in that it is a file that contains the file names
|
||||
instead of taking them on the command line. See \fBCommand Files\fP below.
|
||||
|
|
@ -133,12 +134,29 @@ parameter assignment is evaluated as a lossless expression, as is any
|
|||
expression containing an unsized constant number, and unsized constant
|
||||
numbers are not truncated to integer width.
|
||||
.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
|
||||
Append directory \fIincludedir\fP to list of directories searched
|
||||
for Verilog include files. The \fB\-I\fP switch may be used many times
|
||||
to specify several directories to search, the directories are searched
|
||||
in the order they appear on the command line.
|
||||
.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
|
||||
This is equivalent to \fB\-Mall=path\fP. Preserved for backwards
|
||||
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
|
||||
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
|
||||
.B -y\ \fIlibdir\fP
|
||||
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
|
||||
.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
|
||||
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
|
||||
* 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"
|
||||
" [-N file] [-o filename] [-p flag=value]\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"
|
||||
"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_strict_ca_eval = "no-strict-ca-eval";
|
||||
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";
|
||||
|
||||
/* Boolean: true means use a default include dir, false means don't */
|
||||
|
|
@ -496,6 +497,7 @@ static void process_warning_switch(const char*name)
|
|||
if (strcmp(name,"all") == 0) {
|
||||
process_warning_switch("anachronisms");
|
||||
process_warning_switch("implicit");
|
||||
process_warning_switch("implicit-dimensions");
|
||||
process_warning_switch("portbind");
|
||||
process_warning_switch("select-range");
|
||||
process_warning_switch("timescale");
|
||||
|
|
@ -506,6 +508,9 @@ static void process_warning_switch(const char*name)
|
|||
} else if (strcmp(name,"implicit") == 0) {
|
||||
if (! strchr(warning_flags, 'i'))
|
||||
strcat(warning_flags, "i");
|
||||
} else if (strcmp(name,"implicit-dimensions") == 0) {
|
||||
if (! strchr(warning_flags, 'd'))
|
||||
strcat(warning_flags, "d");
|
||||
} else if (strcmp(name,"portbind") == 0) {
|
||||
if (! strchr(warning_flags, 'p'))
|
||||
strcat(warning_flags, "p");
|
||||
|
|
@ -538,6 +543,12 @@ static void process_warning_switch(const char*name)
|
|||
cp[0] = cp[1];
|
||||
cp += 1;
|
||||
}
|
||||
} else if (strcmp(name,"no-implicit-dimensions") == 0) {
|
||||
char*cp = strchr(warning_flags, 'd');
|
||||
if (cp) while (*cp) {
|
||||
cp[0] = cp[1];
|
||||
cp += 1;
|
||||
}
|
||||
} else if (strcmp(name,"no-portbind") == 0) {
|
||||
char*cp = strchr(warning_flags, 'p');
|
||||
if (cp) while (*cp) {
|
||||
|
|
@ -720,6 +731,12 @@ static int process_generation(const char*name)
|
|||
else if (strcmp(name,"no-strict-expr-width") == 0)
|
||||
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)
|
||||
gen_verilog_ams = "verilog-ams";
|
||||
|
||||
|
|
@ -745,7 +762,8 @@ static int process_generation(const char*name)
|
|||
" icarus-misc | no-icarus-misc\n"
|
||||
" io-range-error | no-io-range-error\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;
|
||||
}
|
||||
|
|
@ -910,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) {
|
||||
case 'B':
|
||||
|
|
@ -965,6 +983,10 @@ int main(int argc, char **argv)
|
|||
process_include_dir(optarg);
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
process_file_name(optarg, 1);
|
||||
break;
|
||||
|
||||
case 'M':
|
||||
if (process_depfile(optarg) != 0)
|
||||
return -1;
|
||||
|
|
@ -1047,19 +1069,10 @@ int main(int argc, char **argv)
|
|||
|
||||
if (version_flag || verbose_flag) {
|
||||
printf("Icarus Verilog version " VERSION " (" VERSION_TAG ")\n\n");
|
||||
printf("Copyright 1998-2013 Stephen Williams\n\n");
|
||||
printf("Copyright 1998-2015 Stephen Williams\n\n");
|
||||
puts(NOTICE);
|
||||
}
|
||||
|
||||
if (synth_flag) {
|
||||
fprintf(stderr, "Warning: Synthesis is not currently being "
|
||||
"maintained and may not\n");
|
||||
fprintf(stderr, " function correctly. V0.8 was the "
|
||||
"last release branch to\n");
|
||||
fprintf(stderr, " have active synthesis development "
|
||||
"and support!\n");
|
||||
}
|
||||
|
||||
/* Make a common conf file path to reflect the target. */
|
||||
snprintf(iconfig_common_path, sizeof iconfig_common_path, "%s%c%s%s.conf",
|
||||
base, sep, targ, synth_flag? "-s" : "");
|
||||
|
|
@ -1107,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_strict_ca_eval);
|
||||
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_icarus);
|
||||
fprintf(iconfig_file, "warnings:%s\n", warning_flags);
|
||||
|
|
|
|||
138
elab_expr.cc
138
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)
|
||||
*
|
||||
* 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,
|
||||
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) {
|
||||
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,
|
||||
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);
|
||||
tmp->set_line(*this);
|
||||
|
||||
tmp = pad_to_width(tmp, expr_wid, *this);
|
||||
tmp->cast_signed(signed_flag_);
|
||||
|
||||
return tmp;
|
||||
return pad_to_width(tmp, expr_wid, signed_flag_, *this);
|
||||
}
|
||||
|
||||
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);
|
||||
tmp->set_line(*this);
|
||||
|
||||
tmp = pad_to_width(tmp, expr_wid, *this);
|
||||
tmp->cast_signed(signed_flag_);
|
||||
|
||||
return tmp;
|
||||
return pad_to_width(tmp, expr_wid, signed_flag_, *this);
|
||||
}
|
||||
|
||||
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 = new NetESelect(lp, tmp, 1);
|
||||
tmp->set_line(*this);
|
||||
tmp = pad_to_width(tmp, expr_wid, *this);
|
||||
tmp->cast_signed(true);
|
||||
tmp = pad_to_width(tmp, expr_wid, true, *this);
|
||||
|
||||
delete rp;
|
||||
return tmp;
|
||||
|
|
@ -1414,23 +1407,7 @@ NetExpr*PECallFunction::cast_to_width_(NetExpr*expr, unsigned wid) const
|
|||
<< " from expr_width()=" << expr->expr_width() << endl;
|
||||
}
|
||||
|
||||
/* 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(*this);
|
||||
delete expr;
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetESelect*tmp = new NetESelect(expr, 0, wid);
|
||||
tmp->cast_signed(signed_flag_);
|
||||
tmp->set_line(*this);
|
||||
|
||||
return tmp;
|
||||
return cast_to_width(expr, wid, signed_flag_, *this);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -1606,10 +1583,7 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope,
|
|||
if (missing_parms || parm_errors)
|
||||
return 0;
|
||||
|
||||
NetExpr*tmp = pad_to_width(fun, expr_wid, *this);
|
||||
tmp->cast_signed(signed_flag_);
|
||||
|
||||
return tmp;
|
||||
return pad_to_width(fun, expr_wid, signed_flag_, *this);
|
||||
}
|
||||
|
||||
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);
|
||||
tmp->set_line(*this);
|
||||
|
||||
tmp = pad_to_width(tmp, expr_wid, *this);
|
||||
tmp->cast_signed(signed_flag_);
|
||||
|
||||
return tmp;
|
||||
return pad_to_width(tmp, expr_wid, signed_flag_, *this);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -2281,10 +2252,7 @@ NetExpr* PECallFunction::elaborate_base_(Design*des, NetScope*scope, NetScope*ds
|
|||
if(res->darray_type())
|
||||
return func;
|
||||
|
||||
NetExpr*tmp = pad_to_width(func, expr_wid, *this);
|
||||
tmp->cast_signed(signed_flag_);
|
||||
|
||||
return tmp;
|
||||
return pad_to_width(func, expr_wid, signed_flag_, *this);
|
||||
}
|
||||
|
||||
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&)
|
||||
{
|
||||
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;
|
||||
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,
|
||||
unsigned, unsigned) const
|
||||
unsigned expr_wid, unsigned flags) const
|
||||
{
|
||||
NetExpr*sub = base_->elaborate_expr(des, scope, base_->expr_width(), NO_FLAGS);
|
||||
NetESelect*sel = new NetESelect(sub, 0, size_);
|
||||
sel->set_line(*this);
|
||||
flags &= ~SYS_TASK_ARG; // don't propagate the SYS_TASK_ARG flag
|
||||
|
||||
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)
|
||||
|
|
@ -2640,17 +2640,15 @@ NetExpr* PECastType::elaborate_expr(Design*des, NetScope*scope,
|
|||
|
||||
if((base_->expr_type() != IVL_VT_BOOL) &&
|
||||
(base_->expr_type() != IVL_VT_LOGIC)) {
|
||||
cerr << get_fileline() << ": cannot be casted to string." << endl;
|
||||
cerr << get_fileline() << ": cannot be cast to a string." << endl;
|
||||
ivl_assert(*this, false);
|
||||
}
|
||||
|
||||
return expr;
|
||||
}
|
||||
|
||||
cerr << get_fileline() << ": sorry: I don't know how to cast expression." << endl;
|
||||
ivl_assert(*this, false);
|
||||
|
||||
return expr;
|
||||
cerr << get_fileline() << ": sorry: This cast operation is not yet supported." << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned PEConcat::test_width(Design*des, NetScope*scope, width_mode_t&)
|
||||
|
|
@ -2842,17 +2840,16 @@ NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope,
|
|||
concat->set(idx, parms[off+idx]);
|
||||
}
|
||||
|
||||
if (wid_sum == 0 && concat_depth < 2) {
|
||||
cerr << get_fileline() << ": error: Concatenation may not "
|
||||
<< "have zero width in this context." << endl;
|
||||
if (wid_sum == 0) {
|
||||
cerr << get_fileline() << ": error: Concatenation/replication "
|
||||
<< "may not have zero width in this context." << endl;
|
||||
des->errors += 1;
|
||||
concat_depth -= 1;
|
||||
delete concat;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetExpr*tmp = pad_to_width(concat, expr_wid, *this);
|
||||
tmp->cast_signed(signed_flag_);
|
||||
NetExpr*tmp = pad_to_width(concat, expr_wid, signed_flag_, *this);
|
||||
|
||||
concat_depth -= 1;
|
||||
return tmp;
|
||||
|
|
@ -3769,10 +3766,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
|||
|
||||
if (!tmp) return 0;
|
||||
|
||||
tmp = pad_to_width(tmp, expr_wid, *this);
|
||||
tmp->cast_signed(signed_flag_);
|
||||
|
||||
return tmp;
|
||||
return pad_to_width(tmp, expr_wid, signed_flag_, *this);
|
||||
}
|
||||
|
||||
// If the identifier names a signal (a register or wire)
|
||||
|
|
@ -3808,10 +3802,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
|||
<< ", tmp=" << *tmp << endl;
|
||||
}
|
||||
|
||||
tmp = pad_to_width(tmp, expr_wid, *this);
|
||||
tmp->cast_signed(signed_flag_);
|
||||
|
||||
return tmp;
|
||||
return pad_to_width(tmp, expr_wid, signed_flag_, *this);
|
||||
}
|
||||
|
||||
// If the identifier is a named event
|
||||
|
|
@ -3911,9 +3902,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
|||
member_comp);
|
||||
if (!tmp) return 0;
|
||||
|
||||
tmp = pad_to_width(tmp, expr_wid, *this);
|
||||
tmp->cast_signed(signed_flag_);
|
||||
return tmp;
|
||||
return pad_to_width(tmp, expr_wid, signed_flag_, *this);
|
||||
}
|
||||
|
||||
if (net->class_type() != 0) {
|
||||
|
|
@ -4492,7 +4481,7 @@ NetExpr* PEIdent::elaborate_expr_param_(Design*des,
|
|||
<< "Elaborate parameter <" << path_
|
||||
<< "> as enumeration constant." << *etmp << endl;
|
||||
tmp = etmp->dup_expr();
|
||||
tmp = pad_to_width(tmp, expr_wid, *this);
|
||||
tmp = pad_to_width(tmp, expr_wid, signed_flag_, *this);
|
||||
|
||||
} else {
|
||||
perm_string name = peek_tail_name(path_);
|
||||
|
|
@ -5011,6 +5000,8 @@ NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope,
|
|||
ivl_assert(*this, index_tail.lsb == 0);
|
||||
|
||||
NetExpr*mux = elab_and_eval(des, scope, index_tail.msb, -1, need_const);
|
||||
if (!mux)
|
||||
return 0;
|
||||
|
||||
if (const netdarray_t*darray = net->sig()->darray_type()) {
|
||||
// Special case: This is a select of a dynamic
|
||||
|
|
@ -5686,7 +5677,6 @@ unsigned PETernary::test_width(Design*des, NetScope*scope, width_mode_t&mode)
|
|||
} else if (tru_type == IVL_VT_LOGIC || fal_type == IVL_VT_LOGIC) {
|
||||
expr_type_ = IVL_VT_LOGIC;
|
||||
} else {
|
||||
ivl_assert(*this, tru_type == fal_type);
|
||||
expr_type_ = tru_type;
|
||||
}
|
||||
if (expr_type_ == IVL_VT_REAL) {
|
||||
|
|
@ -6082,7 +6072,7 @@ NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope,
|
|||
}
|
||||
tmp->set_line(*this);
|
||||
}
|
||||
tmp = pad_to_width(tmp, expr_wid, *this);
|
||||
tmp = pad_to_width(tmp, expr_wid, signed_flag_, *this);
|
||||
break;
|
||||
|
||||
case '&': // Reduction AND
|
||||
|
|
@ -6100,7 +6090,7 @@ NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope,
|
|||
}
|
||||
tmp = new NetEUReduce(op_, ip);
|
||||
tmp->set_line(*this);
|
||||
tmp = pad_to_width(tmp, expr_wid, *this);
|
||||
tmp = pad_to_width(tmp, expr_wid, signed_flag_, *this);
|
||||
break;
|
||||
|
||||
case '~':
|
||||
|
|
|
|||
55
elab_lval.cc
55
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)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
|
|
@ -138,6 +138,9 @@ NetAssign_* PEConcat::elaborate_lval(Design*des,
|
|||
continue;
|
||||
}
|
||||
|
||||
/* A concatenation is always unsigned. */
|
||||
tmp->set_signed(false);
|
||||
|
||||
/* Link the new l-value to the previous one. */
|
||||
NetAssign_*last = tmp;
|
||||
while (last->more)
|
||||
|
|
@ -287,13 +290,13 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
|||
}
|
||||
|
||||
// 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,
|
||||
// then this is "a.b.c.method" and "a.b.c" is a struct or class.)
|
||||
const name_component_t&name_tail = path_.back();
|
||||
|
||||
// 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
|
||||
// be simple expressions, only the <index> may be a part
|
||||
// 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. */
|
||||
|
||||
NetAssign_*lv = new NetAssign_(reg);
|
||||
lv->set_signed(reg->get_signed());
|
||||
|
||||
return lv;
|
||||
}
|
||||
|
|
@ -687,20 +691,24 @@ bool PEIdent::elaborate_lval_net_bit_(Design*des,
|
|||
unsigned long lwid;
|
||||
bool rcl = reg->sb_to_slice(prefix_indices, lsb, loff, lwid);
|
||||
ivl_assert(*this, rcl);
|
||||
cerr << get_fileline() << ": warning: L-value packed array "
|
||||
<< "select of " << reg->name();
|
||||
if (reg->unpacked_dimensions() > 0) cerr << "[]";
|
||||
cerr << " has an undefined index." << endl;
|
||||
|
||||
if (warn_ob_select) {
|
||||
cerr << get_fileline()
|
||||
<< ": warning: L-value packed array select of "
|
||||
<< reg->name();
|
||||
if (reg->unpacked_dimensions() > 0) cerr << "[]";
|
||||
cerr << " has an undefined index." << endl;
|
||||
}
|
||||
lv->set_part(new NetEConst(verinum(verinum::Vx)), lwid);
|
||||
return true;
|
||||
// The index is undefined and this is a bit select.
|
||||
} else {
|
||||
cerr << get_fileline() << ": warning: L-value bit select of "
|
||||
<< reg->name();
|
||||
if (reg->unpacked_dimensions() > 0) cerr << "[]";
|
||||
cerr << " has an undefined index." << endl;
|
||||
|
||||
if (warn_ob_select) {
|
||||
cerr << get_fileline()
|
||||
<< ": warning: L-value bit select of "
|
||||
<< reg->name();
|
||||
if (reg->unpacked_dimensions() > 0) cerr << "[]";
|
||||
cerr << " has an undefined index." << endl;
|
||||
}
|
||||
lv->set_part(new NetEConst(verinum(verinum::Vx)), 1);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -797,12 +805,10 @@ bool PEIdent::elaborate_lval_net_bit_(Design*des,
|
|||
// Constant bit select that does something useful.
|
||||
long loff = reg->sb_to_idx(prefix_indices,lsb);
|
||||
|
||||
if (loff < 0 || loff >= (long)reg->vector_width()) {
|
||||
cerr << get_fileline() << ": error: bit select "
|
||||
if (warn_ob_select && (loff < 0 || loff >= (long)reg->vector_width())) {
|
||||
cerr << get_fileline() << ": warning: bit select "
|
||||
<< reg->name() << "[" <<lsb<<"]"
|
||||
<< " is out of range." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (reg->type()==NetNet::UNRESOLVED_WIRE) {
|
||||
|
|
@ -868,10 +874,13 @@ bool PEIdent::elaborate_lval_net_part_(Design*des,
|
|||
ivl_assert(*this, reg);
|
||||
|
||||
if (! parts_defined_flag) {
|
||||
cerr << get_fileline() << ": warning: L-value part select of "
|
||||
<< reg->name();
|
||||
if (reg->unpacked_dimensions() > 0) cerr << "[]";
|
||||
cerr << " has an undefined index." << endl;
|
||||
if (warn_ob_select) {
|
||||
cerr << get_fileline()
|
||||
<< ": warning: L-value part select of "
|
||||
<< reg->name();
|
||||
if (reg->unpacked_dimensions() > 0) cerr << "[]";
|
||||
cerr << " has an undefined index." << endl;
|
||||
}
|
||||
// Use a width of two here so we can distinguish between an
|
||||
// undefined bit or part select.
|
||||
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
|
||||
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
|
||||
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 "
|
||||
<< reg->name() << "[" << msb<<":"<<lsb<<"]"
|
||||
<< " is out of range." << endl;
|
||||
|
|
|
|||
87
elab_net.cc
87
elab_net.cc
|
|
@ -328,39 +328,66 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
|
|||
return false;
|
||||
}
|
||||
|
||||
long lidx_tmp = sig->sb_to_idx(prefix_indices, lsb);
|
||||
long midx_tmp = sig->sb_to_idx(prefix_indices, msb);
|
||||
/* Detect reversed indices of a part select. */
|
||||
if (lidx_tmp > midx_tmp) {
|
||||
cerr << get_fileline() << ": error: Part select "
|
||||
<< sig->name() << "[" << msb << ":"
|
||||
<< lsb << "] indices reversed." << endl;
|
||||
cerr << get_fileline() << ": : Did you mean "
|
||||
<< sig->name() << "[" << lsb << ":"
|
||||
<< msb << "]?" << endl;
|
||||
long tmp = midx_tmp;
|
||||
midx_tmp = lidx_tmp;
|
||||
lidx_tmp = tmp;
|
||||
des->errors += 1;
|
||||
}
|
||||
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);
|
||||
|
||||
/* Warn about a part select that is out of range. */
|
||||
if (midx_tmp >= (long)sig->vector_width() || lidx_tmp < 0) {
|
||||
cerr << get_fileline() << ": warning: Part select "
|
||||
<< sig->name();
|
||||
if (sig->unpacked_dimensions() > 0) {
|
||||
cerr << "[]";
|
||||
if (moff > loff) {
|
||||
lidx = loff;
|
||||
midx = moff + mwid - 1;
|
||||
} else {
|
||||
lidx = moff;
|
||||
midx = loff + lwid - 1;
|
||||
}
|
||||
cerr << "[" << msb << ":" << lsb
|
||||
<< "] is out of range." << endl;
|
||||
}
|
||||
/* This is completely out side the signal so just skip it. */
|
||||
if (lidx_tmp >= (long)sig->vector_width() || midx_tmp < 0) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
long lidx_tmp = sig->sb_to_idx(prefix_indices, lsb);
|
||||
long midx_tmp = sig->sb_to_idx(prefix_indices, msb);
|
||||
|
||||
midx = midx_tmp;
|
||||
lidx = lidx_tmp;
|
||||
/* Detect reversed indices of a part select. */
|
||||
if (lidx_tmp > midx_tmp) {
|
||||
cerr << get_fileline() << ": error: Part select "
|
||||
<< sig->name() << "[" << msb << ":"
|
||||
<< lsb << "] indices reversed." << endl;
|
||||
cerr << get_fileline() << ": : Did you mean "
|
||||
<< sig->name() << "[" << lsb << ":"
|
||||
<< msb << "]?" << endl;
|
||||
long tmp = midx_tmp;
|
||||
midx_tmp = lidx_tmp;
|
||||
lidx_tmp = tmp;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
/* Warn about a part select that is out of range. */
|
||||
if (midx_tmp >= (long)sig->vector_width() || lidx_tmp < 0) {
|
||||
cerr << get_fileline() << ": warning: Part select "
|
||||
<< sig->name();
|
||||
if (sig->unpacked_dimensions() > 0) {
|
||||
cerr << "[]";
|
||||
}
|
||||
cerr << "[" << msb << ":" << lsb
|
||||
<< "] is out of range." << endl;
|
||||
}
|
||||
/* This is completely out side the signal so just skip it. */
|
||||
if (lidx_tmp >= (long)sig->vector_width() || midx_tmp < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
midx = midx_tmp;
|
||||
lidx = lidx_tmp;
|
||||
}
|
||||
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)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
|
|
@ -54,6 +54,15 @@
|
|||
# include <cassert>
|
||||
# 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;
|
||||
|
||||
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);
|
||||
use_class->set_class_scope(class_scope);
|
||||
use_class->set_definition_scope(scope);
|
||||
set_scope_timescale(des, class_scope, pclass);
|
||||
|
||||
// Collect the properties, elaborate them, and add them to the
|
||||
// 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->set_line(task);
|
||||
|
||||
if (scope==0)
|
||||
if (scope==0) {
|
||||
set_scope_timescale(des, task_scope, task);
|
||||
des->add_root_task(task_scope, task);
|
||||
}
|
||||
|
||||
if (debug_scopes) {
|
||||
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->set_line(task);
|
||||
|
||||
if (scope==0)
|
||||
if (scope==0) {
|
||||
set_scope_timescale(des, task_scope, task);
|
||||
des->add_root_task(task_scope, task);
|
||||
}
|
||||
|
||||
if (debug_scopes) {
|
||||
cerr << task->get_fileline() << ": elaborate_scope_func: "
|
||||
|
|
@ -793,7 +807,7 @@ void elaborate_rootscope_tasks(Design*des)
|
|||
}
|
||||
|
||||
cerr << cur->second->get_fileline() << ": internal error: "
|
||||
<< "elabortae_rootscope_tasks does not understand "
|
||||
<< "elaborate_rootscope_tasks does not understand "
|
||||
<< "this object," << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
|
@ -1750,11 +1764,7 @@ void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*s
|
|||
|
||||
instances[idx] = my_scope;
|
||||
|
||||
// Set time units and precision.
|
||||
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);
|
||||
set_scope_timescale(des, my_scope, mod);
|
||||
|
||||
// Look for module parameter replacements. The "replace" map
|
||||
// maps parameter name to replacement expression that is
|
||||
|
|
|
|||
35
elab_sig.cc
35
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)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
|
|
@ -976,6 +976,23 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
}
|
||||
|
||||
if (port_set_ || net_set_) {
|
||||
|
||||
if (warn_implicit_dimensions
|
||||
&& port_set_ && net_set_
|
||||
&& net_.empty() && !port_.empty()) {
|
||||
cerr << get_fileline() << ": warning: "
|
||||
<< "var/net declaration of " << basename()
|
||||
<< " inherits dimensions from port declaration." << endl;
|
||||
}
|
||||
|
||||
if (warn_implicit_dimensions
|
||||
&& port_set_ && net_set_
|
||||
&& port_.empty() && !net_.empty()) {
|
||||
cerr << get_fileline() << ": warning: "
|
||||
<< "Port declaration of " << basename()
|
||||
<< " inherits dimensions from var/net." << endl;
|
||||
}
|
||||
|
||||
bool bad_range = false;
|
||||
vector<netrange_t> plist, nlist;
|
||||
/* If they exist get the port definition MSB and LSB */
|
||||
|
|
@ -1168,6 +1185,14 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
|
||||
NetLogic*pull = 0;
|
||||
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::PULLUP
|
||||
: NetLogic::PULLDOWN;
|
||||
|
|
@ -1178,14 +1203,6 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
pull->pin(0).drive1(IVL_DR_SUPPLY);
|
||||
des->add_node(pull);
|
||||
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
|
||||
* 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.
|
||||
*/
|
||||
|
||||
# include "PExpr.h"
|
||||
# include "pform_types.h"
|
||||
# include "netlist.h"
|
||||
# include "netclass.h"
|
||||
# include "netdarray.h"
|
||||
# include "netenum.h"
|
||||
# include "netqueue.h"
|
||||
# include "netparray.h"
|
||||
# include "netscalar.h"
|
||||
# include "netstruct.h"
|
||||
|
|
@ -245,6 +247,16 @@ ivl_type_s* uarray_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
|
|||
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;
|
||||
bool bad_range = evaluate_ranges(des, scope, dimensions, *dims);
|
||||
|
||||
|
|
|
|||
262
elaborate.cc
262
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)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
|
|
@ -36,6 +36,7 @@
|
|||
# include "PEvent.h"
|
||||
# include "PGenerate.h"
|
||||
# include "PPackage.h"
|
||||
# include "PScope.h"
|
||||
# include "PSpec.h"
|
||||
# include "netlist.h"
|
||||
# include "netenum.h"
|
||||
|
|
@ -50,6 +51,9 @@
|
|||
# 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
|
||||
{
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
// module[s] port. sig is the thing outside the module
|
||||
// that connects to the port.
|
||||
|
|
@ -2000,7 +2014,7 @@ void PGModule::elaborate_udp_(Design*des, PUdp*udp, NetScope*scope) const
|
|||
PDelays tmp_del;
|
||||
tmp_del.set_delays(overrides_, false);
|
||||
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,
|
||||
ivl_type_t lv_net_type,
|
||||
ivl_variable_type_t lv_type,
|
||||
unsigned lv_width) const
|
||||
unsigned lv_width,
|
||||
bool force_unsigned) const
|
||||
{
|
||||
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
|
||||
// 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,
|
||||
rval(), is_constant_);
|
||||
rval(), is_constant_, force_unsigned);
|
||||
|
||||
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);
|
||||
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;
|
||||
|
||||
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);
|
||||
|
||||
return cur;
|
||||
|
|
@ -2677,11 +2717,16 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
|
|||
return bl;
|
||||
}
|
||||
|
||||
if (lv->enumeration() &&
|
||||
! lv->enumeration()->matches(rv->enumeration())) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< "Enumeration type mismatch in assignment." << endl;
|
||||
des->errors += 1;
|
||||
if (lv->enumeration()) {
|
||||
if (! rv->enumeration()) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
"This assignment requires an explicit cast." << endl;
|
||||
des->errors += 1;
|
||||
} else if (! lv->enumeration()->matches(rv->enumeration())) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
"Enumeration type mismatch in assignment." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
}
|
||||
|
||||
NetAssign*cur = new NetAssign(lv, rv);
|
||||
|
|
@ -2868,14 +2913,27 @@ NetProc* PBlock::elaborate(Design*des, NetScope*scope) const
|
|||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(nscope);
|
||||
|
||||
elaborate_behaviors_(des, 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)
|
||||
nscope = scope;
|
||||
|
||||
|
|
@ -3778,7 +3836,9 @@ NetProc* PCallTask::elaborate_build_call_(Design*des, NetScope*scope,
|
|||
expression that can be a target to a procedural
|
||||
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);
|
||||
|
||||
|
|
@ -3794,12 +3854,12 @@ NetProc* PCallTask::elaborate_build_call_(Design*des, NetScope*scope,
|
|||
message. Note that the elaborate_lval method already
|
||||
printed a detailed message for the latter case. */
|
||||
NetAssign_*lv = 0;
|
||||
if (idx < parms_.size() && parms_[idx]) {
|
||||
lv = parms_[idx]->elaborate_lval(des, scope, false, false);
|
||||
if (parms_idx < parms_.size() && parms_[parms_idx]) {
|
||||
lv = parms_[parms_idx]->elaborate_lval(des, scope, false, false);
|
||||
if (lv == 0) {
|
||||
cerr << parms_[idx]->get_fileline() << ": error: "
|
||||
cerr << parms_[parms_idx]->get_fileline() << ": error: "
|
||||
<< "I give up on task port " << (idx+1)
|
||||
<< " expression: " << *parms_[idx] << endl;
|
||||
<< " expression: " << *parms_[parms_idx] << endl;
|
||||
}
|
||||
} else if (port->port_type() == NetNet::POUTPUT) {
|
||||
// Output ports were skipped earlier, so
|
||||
|
|
@ -4039,9 +4099,18 @@ NetProc* PDisable::elaborate(Design*des, NetScope*scope) const
|
|||
*/
|
||||
NetProc* PDoWhile::elaborate(Design*des, NetScope*scope) const
|
||||
{
|
||||
NetExpr*tmp = elab_and_eval(des, scope, cond_, -1);
|
||||
tmp->set_line(*this);
|
||||
NetDoWhile*loop = new NetDoWhile(tmp, statement_->elaborate(des, scope));
|
||||
NetExpr*ce = elab_and_eval(des, scope, cond_, -1);
|
||||
NetProc*sub;
|
||||
if (statement_)
|
||||
sub = statement_->elaborate(des, scope);
|
||||
else
|
||||
sub = new NetBlock(NetBlock::SEQU, 0);
|
||||
if (ce == 0 || sub == 0) {
|
||||
delete ce;
|
||||
delete sub;
|
||||
return 0;
|
||||
}
|
||||
NetDoWhile*loop = new NetDoWhile(ce, sub);
|
||||
loop->set_line(*this);
|
||||
return loop;
|
||||
}
|
||||
|
|
@ -4572,7 +4641,11 @@ NetProc* PEventStatement::elaborate(Design*des, NetScope*scope) const
|
|||
*/
|
||||
NetProc* PForever::elaborate(Design*des, NetScope*scope) const
|
||||
{
|
||||
NetProc*stat = statement_->elaborate(des, scope);
|
||||
NetProc*stat;
|
||||
if (statement_)
|
||||
stat = statement_->elaborate(des, scope);
|
||||
else
|
||||
stat = new NetBlock(NetBlock::SEQU, 0);
|
||||
if (stat == 0) return 0;
|
||||
|
||||
NetForever*proc = new NetForever(stat);
|
||||
|
|
@ -4778,7 +4851,11 @@ NetProc* PForeach::elaborate(Design*des, NetScope*scope) const
|
|||
|
||||
/* Elaborate the statement that is contained in the foreach
|
||||
loop. */
|
||||
NetProc*sub = statement_->elaborate(des, scope);
|
||||
NetProc*sub;
|
||||
if (statement_)
|
||||
sub = statement_->elaborate(des, scope);
|
||||
else
|
||||
sub = new NetBlock(NetBlock::SEQU, 0);
|
||||
|
||||
/* Make a step statement: idx += 1 */
|
||||
NetAssign_*idx_lv = new NetAssign_(idx_sig);
|
||||
|
|
@ -4809,7 +4886,11 @@ NetProc* PForeach::elaborate_static_array_(Design*des, NetScope*scope,
|
|||
ivl_assert(*this, index_vars_.size() > 0);
|
||||
ivl_assert(*this, dims.size() == index_vars_.size());
|
||||
|
||||
NetProc*sub = statement_->elaborate(des, scope);
|
||||
NetProc*sub;
|
||||
if (statement_)
|
||||
sub = statement_->elaborate(des, scope);
|
||||
else
|
||||
sub = new NetBlock(NetBlock::SEQU, 0);
|
||||
NetForLoop*stmt = 0;
|
||||
|
||||
for (int idx_idx = index_vars_.size()-1 ; idx_idx >= 0 ; idx_idx -= 1) {
|
||||
|
|
@ -4903,7 +4984,11 @@ NetProc* PForStatement::elaborate(Design*des, NetScope*scope) const
|
|||
loop. If there is an error, this will return 0 and I should
|
||||
skip the append. No need to worry, the error has been
|
||||
reported so it's OK that the netlist is bogus. */
|
||||
NetProc*sub = statement_->elaborate(des, scope);
|
||||
NetProc*sub;
|
||||
if (statement_)
|
||||
sub = statement_->elaborate(des, scope);
|
||||
else
|
||||
sub = new NetBlock(NetBlock::SEQU, 0);
|
||||
|
||||
/* Now elaborate the for_step statement. I really should do
|
||||
some error checking here to make sure the step statement
|
||||
|
|
@ -4972,7 +5057,6 @@ void PFunction::elaborate(Design*des, NetScope*scope) const
|
|||
des->errors += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
assert(def);
|
||||
|
||||
ivl_assert(*this, statement_);
|
||||
|
|
@ -4985,6 +5069,31 @@ void PFunction::elaborate(Design*des, NetScope*scope) const
|
|||
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);
|
||||
}
|
||||
|
||||
|
|
@ -5025,7 +5134,11 @@ NetProc* PRepeat::elaborate(Design*des, NetScope*scope) const
|
|||
if (expr->expr_type() == IVL_VT_REAL)
|
||||
expr = cast_to_int4(expr, 64);
|
||||
|
||||
NetProc*stat = statement_->elaborate(des, scope);
|
||||
NetProc*stat;
|
||||
if (statement_)
|
||||
stat = statement_->elaborate(des, scope);
|
||||
else
|
||||
stat = new NetBlock(NetBlock::SEQU, 0);
|
||||
if (stat == 0) return 0;
|
||||
|
||||
// If the expression is a constant, handle certain special
|
||||
|
|
@ -5143,11 +5256,6 @@ NetProc* PReturn::elaborate(Design*des, NetScope*scope) 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();
|
||||
assert(def);
|
||||
|
||||
|
|
@ -5166,6 +5274,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);
|
||||
}
|
||||
|
||||
|
|
@ -5205,7 +5338,11 @@ NetProc* PTrigger::elaborate(Design*des, NetScope*scope) const
|
|||
NetProc* PWhile::elaborate(Design*des, NetScope*scope) const
|
||||
{
|
||||
NetExpr*ce = elab_and_eval(des, scope, cond_, -1);
|
||||
NetProc*sub = statement_->elaborate(des, scope);
|
||||
NetProc*sub;
|
||||
if (statement_)
|
||||
sub = statement_->elaborate(des, scope);
|
||||
else
|
||||
sub = new NetBlock(NetBlock::SEQU, 0);
|
||||
if (ce == 0 || sub == 0) {
|
||||
delete ce;
|
||||
delete sub;
|
||||
|
|
@ -5618,6 +5755,10 @@ bool Module::elaborate(Design*des, NetScope*scope) const
|
|||
(*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
|
||||
// involves scanning the PProcess* list, creating a NetProcTop
|
||||
// for each process.
|
||||
|
|
@ -5695,6 +5836,9 @@ bool PGenerate::elaborate(Design*des, NetScope*container) const
|
|||
"generate " << scheme_type
|
||||
<< " elaborating in scope " << scope_path(container)
|
||||
<< "." << endl;
|
||||
cerr << get_fileline() << ": PGenerate::elaborate: "
|
||||
"generate scope_name=" << scope_name
|
||||
<< ", id_number=" << id_number << endl;
|
||||
}
|
||||
|
||||
// Handle the special case that this is a CASE scheme. In this
|
||||
|
|
@ -5729,6 +5873,7 @@ bool PGenerate::elaborate(Design*des, NetScope*container) const
|
|||
// scheme defined in the Verilog-2005 standard.
|
||||
const char*name = scope_name.str();
|
||||
if (name[0] == '$') {
|
||||
|
||||
if (!scope->auto_name("genblk", '0', name + 4)) {
|
||||
cerr << get_fileline() << ": warning: Couldn't build"
|
||||
<< " unique name for unnamed generate block"
|
||||
|
|
@ -5804,6 +5949,8 @@ bool PGenerate::elaborate_(Design*des, NetScope*scope) const
|
|||
for (gates_it_t cur = gates.begin() ; cur != gates.end() ; ++ cur )
|
||||
(*cur)->elaborate(des, scope);
|
||||
|
||||
elaborate_var_inits_(des, scope);
|
||||
|
||||
typedef list<PProcess*>::const_iterator proc_it_t;
|
||||
for (proc_it_t cur = behaviors.begin(); cur != behaviors.end(); ++ cur )
|
||||
(*cur)->elaborate(des, scope);
|
||||
|
|
@ -5839,6 +5986,44 @@ bool PScope::elaborate_behaviors_(Design*des, NetScope*scope) const
|
|||
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 {
|
||||
public:
|
||||
elaborate_package_t(Design*d, NetScope*scope, PPackage*p)
|
||||
|
|
@ -6072,6 +6257,7 @@ Design* elaborate(list<perm_string>roots)
|
|||
ivl_assert(*pac->second, pac->first == pac->second->pscope_name());
|
||||
NetScope*scope = des->make_package_scope(pac->first);
|
||||
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);
|
||||
des->elaboration_work_list.push_back(es);
|
||||
|
|
@ -6108,11 +6294,7 @@ Design* elaborate(list<perm_string>roots)
|
|||
// Collect some basic properties of this scope from the
|
||||
// Module definition.
|
||||
scope->set_line(rmod);
|
||||
scope->time_unit(rmod->time_unit);
|
||||
scope->time_precision(rmod->time_precision);
|
||||
scope->time_from_timescale(rmod->time_from_timescale);
|
||||
des->set_precision(rmod->time_precision);
|
||||
|
||||
set_scope_timescale(des, scope, rmod);
|
||||
|
||||
// Save this scope, along with its definition, in the
|
||||
// "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()
|
||||
; scope != root_tasks_.end() ; ++ scope) {
|
||||
scope->first->emit_scope(tgt);
|
||||
scope->first->emit_defs(tgt);
|
||||
}
|
||||
|
||||
// enumerate package scopes
|
||||
|
|
@ -521,7 +520,6 @@ int Design::emit(struct target_t*tgt) const
|
|||
const NetScope*use_scope = cur->second->class_scope();
|
||||
cur->second->emit_scope(tgt);
|
||||
tgt->class_type(use_scope, cur->second);
|
||||
cur->second->emit_defs(tgt);
|
||||
}
|
||||
|
||||
// enumerate root scopes
|
||||
|
|
@ -548,6 +546,12 @@ int Design::emit(struct target_t*tgt) const
|
|||
|
||||
// emit task and function definitions
|
||||
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()
|
||||
; scope != packages_.end() ; ++ scope )
|
||||
tasks_rc &= scope->second->emit_defs(tgt);
|
||||
|
|
|
|||
11
eval_tree.cc
11
eval_tree.cc
|
|
@ -697,7 +697,9 @@ NetEConst* NetEBComp::eval_eqeqeq_(bool ne_flag, const NetExpr*le, const NetExpr
|
|||
// If the left value is longer check it against the pad bit.
|
||||
if (res == verinum::V1) {
|
||||
verinum::V pad = verinum::V0;
|
||||
if (is_signed) pad = rv.get(rv.len()-1);
|
||||
if (is_signed)
|
||||
pad = rv.get(rv.len()-1);
|
||||
|
||||
for (unsigned idx = cnt ; idx < lv.len() ; idx += 1)
|
||||
if (lv.get(idx) != pad) {
|
||||
res = verinum::V0;
|
||||
|
|
@ -708,12 +710,15 @@ NetEConst* NetEBComp::eval_eqeqeq_(bool ne_flag, const NetExpr*le, const NetExpr
|
|||
// If the right value is longer check it against the pad bit.
|
||||
if (res == verinum::V1) {
|
||||
verinum::V pad = verinum::V0;
|
||||
if (is_signed) pad = lv.get(lv.len()-1);
|
||||
if (is_signed)
|
||||
pad = lv.get(lv.len()-1);
|
||||
|
||||
for (unsigned idx = cnt ; idx < rv.len() ; idx += 1) {
|
||||
if (rv.get(idx) != pad)
|
||||
if (rv.get(idx) != pad) {
|
||||
res = verinum::V0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ne_flag) {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
.TH iverilog-vpi 1 "May 10th, 2015" "" "Version %M.%m.%n %E"
|
||||
.TH iverilog-vpi 1 "Jan 29th, 2017" "" "Version %M.%n%E"
|
||||
.SH NAME
|
||||
iverilog-vpi - Compile front end for VPI modules
|
||||
|
||||
|
|
@ -26,6 +26,11 @@ becomes \fIfoo.vpi\fP.
|
|||
Include the named library in the link of the VPI module. This allows
|
||||
VPI modules to further reference external libraries.
|
||||
|
||||
.TP 8
|
||||
.B -L\fIdirectory\fP
|
||||
Add \fIdirectory\fP to the list of directories that will be searched
|
||||
for library files.
|
||||
|
||||
.TP 8
|
||||
.B -I\fIdirectory\fP
|
||||
Add \fIdirectory\fP to the list of directories that will be searched
|
||||
|
|
@ -115,7 +120,7 @@ iverilog(1), vvp(1),
|
|||
|
||||
.SH COPYRIGHT
|
||||
.nf
|
||||
Copyright \(co 2002\-2015 Stephen Williams
|
||||
Copyright \(co 2002\-2017 Stephen Williams
|
||||
|
||||
This document can be freely redistributed according to the terms of the
|
||||
GNU General Public License version 2.0
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ CCSRC=
|
|||
CXSRC=
|
||||
OBJ=
|
||||
LIB=
|
||||
LIBDIR=
|
||||
OUT=
|
||||
INCOPT=
|
||||
DEFS=
|
||||
|
|
@ -81,6 +82,9 @@ do
|
|||
-l*) LIB="$LIB $parm"
|
||||
;;
|
||||
|
||||
-L*) LIBDIR="$LIBDIR $parm"
|
||||
;;
|
||||
|
||||
-I*) INCOPT="$INCOPT $parm"
|
||||
;;
|
||||
|
||||
|
|
@ -148,4 +152,4 @@ then
|
|||
fi
|
||||
|
||||
echo "Making $OUT from $OBJ..."
|
||||
exec $LD -o $OUT $LDFLAGS $OBJ $LIB $LDLIBS
|
||||
exec $LD -o $OUT $LDFLAGS $LIBDIR $OBJ $LIB $LDLIBS
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
%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
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -148,18 +148,38 @@ static void ifdef_leave(void)
|
|||
free(cur);
|
||||
}
|
||||
|
||||
#define YY_INPUT(buf,result,max_size) do { \
|
||||
if (istack->file) { \
|
||||
size_t rc = fread(buf, 1, max_size, istack->file); \
|
||||
result = (rc == 0) ? YY_NULL : rc; \
|
||||
} else { \
|
||||
if (*istack->str == 0) \
|
||||
result = YY_NULL; \
|
||||
else { \
|
||||
buf[0] = *istack->str++; \
|
||||
result = 1; \
|
||||
} \
|
||||
} \
|
||||
#define YY_INPUT(buf,result,max_size) do { \
|
||||
if (istack->file) { \
|
||||
size_t rc = fread(buf, 1, max_size, istack->file); \
|
||||
result = (rc == 0) ? YY_NULL : rc; \
|
||||
} else { \
|
||||
/* 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; \
|
||||
} 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++; \
|
||||
result = 1; \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static int comment_enter = 0;
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
||||
/* `" 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
|
||||
* macros. If that happens, they get expanded in the context of the
|
||||
* string.
|
||||
|
|
@ -514,29 +528,19 @@ keywords (include|define|undef|ifdef|ifndef|else|elseif|endif)
|
|||
do_expand(0);
|
||||
}
|
||||
|
||||
/* Stringified version of macro expansion. If the sequence `` is
|
||||
* encountered inside a macro definition, we use the SystemVerilog
|
||||
* 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.
|
||||
*/
|
||||
/* Stringified version of macro expansion. This is an Icarus extension.
|
||||
When expanding macro text, the SV usage of `` takes precedence. */
|
||||
``[a-zA-Z_][a-zA-Z0-9_$]* {
|
||||
if (istack->file == NULL)
|
||||
fprintf(yyout, "%s", yytext+2);
|
||||
else {
|
||||
assert(do_expand_stringify_flag == 0);
|
||||
do_expand_stringify_flag = 1;
|
||||
fputc('"', yyout);
|
||||
if (macro_needs_args(yytext+2))
|
||||
yy_push_state(MA_START);
|
||||
else
|
||||
do_expand(0);
|
||||
}
|
||||
assert(istack->file);
|
||||
assert(do_expand_stringify_flag == 0);
|
||||
do_expand_stringify_flag = 1;
|
||||
fputc('"', yyout);
|
||||
if (macro_needs_args(yytext+2))
|
||||
yy_push_state(MA_START);
|
||||
else
|
||||
do_expand(0);
|
||||
}
|
||||
|
||||
`` { if (istack->file != NULL) ECHO; }
|
||||
|
||||
<MA_START>\( { BEGIN(MA_ADD); macro_start_args(); }
|
||||
|
||||
<MA_START>{W} {}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
const char COPYRIGHT[] =
|
||||
"Copyright (c) 1999-2011 Stephen Williams (steve@icarus.com)";
|
||||
"Copyright (c) 1999-2011,2015 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
|
||||
|
|
|
|||
38
lexor.lex
38
lexor.lex
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
%{
|
||||
/*
|
||||
* Copyright (c) 1998-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2015 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
|
||||
|
|
@ -432,18 +432,28 @@ TU [munpf]
|
|||
return SYSTEM_IDENTIFIER; }
|
||||
|
||||
|
||||
\'[sS]?[dD][ \t]*[0-9][0-9_]* { yylval.number = make_unsized_dec(yytext);
|
||||
return BASED_NUMBER; }
|
||||
\'[sS]?[dD][ \t]*[xzXZ?]_* { yylval.number = make_undef_highz_dec(yytext);
|
||||
return BASED_NUMBER; }
|
||||
\'[sS]?[bB][ \t]*[0-1xzXZ_\?]+ { yylval.number = make_unsized_binary(yytext);
|
||||
return BASED_NUMBER; }
|
||||
\'[sS]?[oO][ \t]*[0-7xzXZ_\?]+ { yylval.number = make_unsized_octal(yytext);
|
||||
return BASED_NUMBER; }
|
||||
\'[sS]?[hH][ \t]*[0-9a-fA-FxzXZ_\?]+ { yylval.number = make_unsized_hex(yytext);
|
||||
return BASED_NUMBER; }
|
||||
\'[sS]?[dD][ \t]*[0-9][0-9_]* {
|
||||
yylval.number = make_unsized_dec(yytext);
|
||||
return BASED_NUMBER;
|
||||
}
|
||||
\'[sS]?[dD][ \t]*[xzXZ?]_* {
|
||||
yylval.number = make_undef_highz_dec(yytext);
|
||||
return BASED_NUMBER;
|
||||
}
|
||||
\'[sS]?[bB][ \t]*[0-1xzXZ?][0-1xzXZ?_]* {
|
||||
yylval.number = make_unsized_binary(yytext);
|
||||
return BASED_NUMBER;
|
||||
}
|
||||
\'[sS]?[oO][ \t]*[0-7xzXZ?][0-7xzXZ?_]* {
|
||||
yylval.number = make_unsized_octal(yytext);
|
||||
return BASED_NUMBER;
|
||||
}
|
||||
\'[sS]?[hH][ \t]*[0-9a-fA-FxzXZ?][0-9a-fA-FxzXZ?_]* {
|
||||
yylval.number = make_unsized_hex(yytext);
|
||||
return BASED_NUMBER;
|
||||
}
|
||||
\'[01xzXZ] {
|
||||
if (generation_flag < GN_VER2005_SV) {
|
||||
if (!gn_system_verilog()) {
|
||||
cerr << yylloc.text << ":" << yylloc.first_line << ": warning: "
|
||||
<< "Using SystemVerilog 'N bit vector. Use at least "
|
||||
<< "-g2005-sv to remove this warning." << endl;
|
||||
|
|
@ -469,7 +479,7 @@ TU [munpf]
|
|||
|
||||
/* This rule handles scaled time values for SystemVerilog. */
|
||||
[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);
|
||||
return TIME_LITERAL;
|
||||
} else REJECT; }
|
||||
|
|
@ -847,7 +857,7 @@ verinum*make_unsized_binary(const char*txt)
|
|||
ptr += 1;
|
||||
}
|
||||
|
||||
assert((tolower(*ptr) == 'b') || (generation_flag >= GN_VER2005_SV));
|
||||
assert((tolower(*ptr) == 'b') || gn_system_verilog());
|
||||
if (tolower(*ptr) == 'b') {
|
||||
ptr += 1;
|
||||
} else {
|
||||
|
|
|
|||
15
main.cc
15
main.cc
|
|
@ -1,5 +1,5 @@
|
|||
const char COPYRIGHT[] =
|
||||
"Copyright (c) 1998-2014 Stephen Williams (steve@icarus.com)";
|
||||
"Copyright (c) 1998-2015 Stephen Williams (steve@icarus.com)";
|
||||
|
||||
/*
|
||||
* This source code is free software; you can redistribute it
|
||||
|
|
@ -108,6 +108,7 @@ bool gn_assertions_flag = true;
|
|||
bool gn_io_range_error_flag = true;
|
||||
bool gn_strict_ca_eval_flag = false;
|
||||
bool gn_strict_expr_width_flag = false;
|
||||
bool gn_shared_loop_index_flag = false;
|
||||
bool gn_verilog_ams_flag = false;
|
||||
|
||||
/*
|
||||
|
|
@ -153,6 +154,7 @@ FILE *depend_file = NULL;
|
|||
* These are the warning enable flags.
|
||||
*/
|
||||
bool warn_implicit = false;
|
||||
bool warn_implicit_dimensions = false;
|
||||
bool warn_timescale = false;
|
||||
bool warn_portbinding = false;
|
||||
bool warn_inf_loop = false;
|
||||
|
|
@ -343,6 +345,12 @@ static void process_generation_flag(const char*gen)
|
|||
} else if (strcmp(gen,"no-strict-expr-width") == 0) {
|
||||
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 {
|
||||
}
|
||||
}
|
||||
|
|
@ -678,6 +686,9 @@ static void read_iconfig_file(const char*ipath)
|
|||
case 'i':
|
||||
warn_implicit = true;
|
||||
break;
|
||||
case 'd':
|
||||
warn_implicit_dimensions = true;
|
||||
break;
|
||||
case 'l':
|
||||
warn_inf_loop = true;
|
||||
break;
|
||||
|
|
@ -1107,7 +1118,7 @@ int main(int argc, char*argv[])
|
|||
|
||||
/* Decide if we are going to allow system functions to be called
|
||||
* as tasks. */
|
||||
if (generation_flag >= GN_VER2005_SV) {
|
||||
if (gn_system_verilog()) {
|
||||
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)
|
||||
{
|
||||
more = 0;
|
||||
signed_ = false;
|
||||
turn_sig_to_wire_on_release_ = false;
|
||||
}
|
||||
|
||||
NetAssign_::NetAssign_(NetNet*s)
|
||||
|
|
@ -51,6 +53,7 @@ NetAssign_::NetAssign_(NetNet*s)
|
|||
lwid_ = sig_->vector_width();
|
||||
sig_->incr_lref();
|
||||
more = 0;
|
||||
signed_ = false;
|
||||
turn_sig_to_wire_on_release_ = false;
|
||||
}
|
||||
|
||||
|
|
|
|||
154
net_func_eval.cc
154
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
|
||||
* 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.
|
||||
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) {
|
||||
cerr << loc.get_fileline() << ": NetFuncDef::evaluate_function: "
|
||||
<< "Function " << scope_path(scope())
|
||||
|
|
@ -209,6 +213,98 @@ bool NetProc::evaluate_function(const LineInfo&,
|
|||
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,
|
||||
map<perm_string,LocalVar>&context_map,
|
||||
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());
|
||||
|
||||
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);
|
||||
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)
|
||||
lval_v.set(idx+base, rval_v[idx]);
|
||||
verinum lpart(verinum::Vx, lval->lwidth());
|
||||
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 rval_result;
|
||||
rval_result = new NetEConst(lval_v);
|
||||
} else {
|
||||
rval_result = fix_assign_value(lval->sig(), rval_result);
|
||||
if (op_ == 0) {
|
||||
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)
|
||||
|
|
@ -318,6 +451,13 @@ bool NetAssign::evaluate_function(const LineInfo&loc,
|
|||
NetEConst*rval_const = dynamic_cast<NetEConst*>(rval_result);
|
||||
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();
|
||||
delete rval_result;
|
||||
|
||||
|
|
@ -369,6 +509,10 @@ bool NetBlock::evaluate_function(const LineInfo&loc,
|
|||
// Now collect the new locals.
|
||||
subscope_->evaluate_function_find_locals(loc, local_context_map);
|
||||
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
|
||||
|
|
|
|||
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
|
||||
{
|
||||
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
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -404,6 +404,17 @@ NexusSet* NetDoWhile::nex_input(bool rem_out)
|
|||
return result;
|
||||
}
|
||||
|
||||
NexusSet* NetEvWait::nex_input(bool rem_out)
|
||||
{
|
||||
NexusSet*result;
|
||||
if (statement_)
|
||||
result = statement_->nex_input(rem_out);
|
||||
else
|
||||
result = new NexusSet;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
NexusSet* NetForce::nex_input(bool)
|
||||
{
|
||||
cerr << get_fileline() << ": internal warning: NetForce::nex_input()"
|
||||
|
|
@ -427,6 +438,15 @@ NexusSet* NetForLoop::nex_input(bool rem_out)
|
|||
result->add(*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;
|
||||
}
|
||||
|
||||
|
|
|
|||
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
|
||||
{
|
||||
if (last_ == 0)
|
||||
|
|
|
|||
40
net_scope.cc
40
net_scope.cc
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2017 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
|
||||
|
|
@ -139,6 +139,7 @@ NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t, bool nest,
|
|||
time_from_timescale_ = false;
|
||||
}
|
||||
|
||||
var_init_ = 0;
|
||||
switch (t) {
|
||||
case NetScope::TASK:
|
||||
task_ = 0;
|
||||
|
|
@ -264,19 +265,20 @@ bool NetScope::auto_name(const char*prefix, char pad, const char* suffix)
|
|||
assert(self != up_->children_.end());
|
||||
assert(self->second == this);
|
||||
|
||||
char tmp[32];
|
||||
int pad_pos = strlen(prefix);
|
||||
int max_pos = sizeof(tmp) - strlen(suffix) - 1;
|
||||
strncpy(tmp, prefix, sizeof(tmp));
|
||||
tmp[31] = 0;
|
||||
// This is to keep the pad attempts from being stuck in some
|
||||
// sort of infinite loop. This should not be a practical
|
||||
// limit, but an extreme one.
|
||||
const size_t max_pad_attempts = 32 + strlen(prefix);
|
||||
|
||||
string use_prefix = prefix;
|
||||
|
||||
// Try a variety of potential new names. Make sure the new
|
||||
// name is not in the parent scope. Keep looking until we are
|
||||
// sure we have a unique name, or we run out of names to try.
|
||||
while (pad_pos <= max_pos) {
|
||||
while (use_prefix.size() <= max_pad_attempts) {
|
||||
// Try this name...
|
||||
strcat(tmp + pad_pos, suffix);
|
||||
hname_t new_name(lex_strings.make(tmp));
|
||||
string tmp = use_prefix + suffix;
|
||||
hname_t new_name(lex_strings.make(tmp.c_str()), name_.peek_numbers());
|
||||
if (!up_->child(new_name)) {
|
||||
// Ah, this name is unique. Rename myself, and
|
||||
// change my name in the parent scope.
|
||||
|
|
@ -285,7 +287,9 @@ bool NetScope::auto_name(const char*prefix, char pad, const char* suffix)
|
|||
up_->children_[name_] = this;
|
||||
return true;
|
||||
}
|
||||
tmp[pad_pos++] = pad;
|
||||
|
||||
// Name collides, so try a different name.
|
||||
use_prefix = use_prefix + pad;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
@ -296,16 +300,16 @@ bool NetScope::auto_name(const char*prefix, char pad, const char* suffix)
|
|||
*/
|
||||
bool NetScope::replace_parameter(perm_string key, PExpr*val, NetScope*scope)
|
||||
{
|
||||
bool flag = false;
|
||||
if (parameters.find(key) == parameters.end())
|
||||
return false;
|
||||
|
||||
if (parameters.find(key) != parameters.end()) {
|
||||
param_expr_t&ref = parameters[key];
|
||||
ref.val_expr = val;
|
||||
ref.val_scope = scope;
|
||||
flag = true;
|
||||
}
|
||||
param_expr_t&ref = parameters[key];
|
||||
if (ref.local_flag)
|
||||
return false;
|
||||
|
||||
return flag;
|
||||
ref.val_expr = val;
|
||||
ref.val_scope = scope;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetScope::make_parameter_unannotatable(perm_string key)
|
||||
|
|
|
|||
12
netlist.cc
12
netlist.cc
|
|
@ -557,7 +557,7 @@ void NetNet::calculate_slice_widths_from_packed_dims_(void)
|
|||
ivl_assert(*this, ! slice_wids_.empty());
|
||||
slice_wids_[0] = netrange_width(slice_dims_);
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
|
@ -2743,10 +2743,11 @@ DelayType NetCase::delay_type() const
|
|||
|
||||
for (unsigned idx = 0; idx < nstmts; idx += 1) {
|
||||
if (!expr(idx)) def_stmt = true;
|
||||
DelayType dt = stat(idx) ? stat(idx)->delay_type() : NO_DELAY;
|
||||
if (idx == 0) {
|
||||
result = stat(idx)->delay_type();
|
||||
result = dt;
|
||||
} else {
|
||||
result = combine_delays(result, stat(idx)->delay_type());
|
||||
result = combine_delays(result, dt);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2769,6 +2770,7 @@ DelayType NetCondit::delay_type() const
|
|||
*/
|
||||
DelayType NetDoWhile::delay_type() const
|
||||
{
|
||||
ivl_assert(*this, proc_);
|
||||
return proc_->delay_type();
|
||||
}
|
||||
|
||||
|
|
@ -2779,11 +2781,13 @@ DelayType NetEvWait::delay_type() const
|
|||
|
||||
DelayType NetForever::delay_type() const
|
||||
{
|
||||
ivl_assert(*this, statement_);
|
||||
return statement_->delay_type();
|
||||
}
|
||||
|
||||
DelayType NetForLoop::delay_type() const
|
||||
{
|
||||
ivl_assert(*this, statement_);
|
||||
return get_loop_delay_type(condition_, statement_);
|
||||
}
|
||||
|
||||
|
|
@ -2806,6 +2810,7 @@ DelayType NetPDelay::delay_type() const
|
|||
|
||||
DelayType NetRepeat::delay_type() const
|
||||
{
|
||||
ivl_assert(*this, statement_);
|
||||
return get_loop_delay_type(expr_, statement_);
|
||||
}
|
||||
|
||||
|
|
@ -2821,5 +2826,6 @@ DelayType NetUTask::delay_type() const
|
|||
|
||||
DelayType NetWhile::delay_type() const
|
||||
{
|
||||
ivl_assert(*this, proc_);
|
||||
return get_loop_delay_type(cond_, proc_);
|
||||
}
|
||||
|
|
|
|||
26
netlist.h
26
netlist.h
|
|
@ -388,6 +388,10 @@ class Nexus {
|
|||
is a variable, but also if this is a net with a force. */
|
||||
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
|
||||
(including variables) attached to this nexus. */
|
||||
bool drivers_present() const;
|
||||
|
|
@ -713,7 +717,7 @@ class NetNet : public NetObj, public PortType {
|
|||
/* This method returns a reference to the packed dimensions
|
||||
for the vector. These are arranged as a list where the
|
||||
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. */
|
||||
const std::vector<netrange_t>& packed_dims() const { return slice_dims_; }
|
||||
|
||||
|
|
@ -1020,6 +1024,13 @@ class NetScope : public Definitions, public Attrib {
|
|||
TYPE type() 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_func_def(NetFuncDef*);
|
||||
void set_class_def(netclass_t*);
|
||||
|
|
@ -1250,6 +1261,8 @@ class NetScope : public Definitions, public Attrib {
|
|||
|
||||
vector<PortInfo> ports_;
|
||||
|
||||
const NetProc*var_init_;
|
||||
|
||||
union {
|
||||
NetTaskDef*task_;
|
||||
NetFuncDef*func_;
|
||||
|
|
@ -2732,6 +2745,12 @@ class NetAssign_ {
|
|||
void set_property(const perm_string&name);
|
||||
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
|
||||
// method accounts for the presence of the mux, so it is not
|
||||
// necessarily the same as the pin_count().
|
||||
|
|
@ -2782,6 +2801,7 @@ class NetAssign_ {
|
|||
// member/property if signal is a class.
|
||||
perm_string member_;
|
||||
|
||||
bool signed_;
|
||||
bool turn_sig_to_wire_on_release_;
|
||||
// indexed part select base
|
||||
NetExpr*base_;
|
||||
|
|
@ -2849,6 +2869,8 @@ class NetAssign : public NetAssignBase {
|
|||
map<perm_string,LocalVar>&ctx) const;
|
||||
|
||||
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,
|
||||
const NetAssign_*lval, NetExpr*rval_result) const;
|
||||
|
||||
|
|
@ -2895,6 +2917,7 @@ class NetBlock : public NetProc {
|
|||
NetScope* subscope() const { return subscope_; }
|
||||
|
||||
void append(NetProc*);
|
||||
void prepend(NetProc*);
|
||||
|
||||
const NetProc*proc_first() const;
|
||||
const NetProc*proc_next(const NetProc*cur) const;
|
||||
|
|
@ -3323,6 +3346,7 @@ class NetEvWait : public NetProc {
|
|||
// process? This method checks.
|
||||
virtual bool is_synchronous();
|
||||
|
||||
virtual NexusSet* nex_input(bool rem_out = true);
|
||||
virtual void nex_output(NexusSet&out);
|
||||
|
||||
virtual bool synth_async(Design*des, NetScope*scope,
|
||||
|
|
|
|||
97
netmisc.cc
97
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
|
||||
* 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());
|
||||
val_v.has_sign(true);
|
||||
val_v.has_sign(expr->has_sign());
|
||||
|
||||
NetEConst*val_c = new NetEConst(val_v);
|
||||
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)
|
||||
{
|
||||
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);
|
||||
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
|
||||
* 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)) ;
|
||||
unsigned use_wid = expr->expr_width() + val_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);
|
||||
val_c->set_line(*expr);
|
||||
|
|
@ -434,17 +453,41 @@ NetExpr *normalize_variable_slice_base(const list<long>&indices, NetExpr*base,
|
|||
-- pcur;
|
||||
}
|
||||
|
||||
long sb;
|
||||
if (pcur->get_msb() >= pcur->get_lsb())
|
||||
sb = pcur->get_lsb();
|
||||
else
|
||||
sb = pcur->get_msb();
|
||||
|
||||
long sb = min(pcur->get_lsb(), pcur->get_msb());
|
||||
long loff;
|
||||
reg->sb_to_slice(indices, sb, loff, lwid);
|
||||
|
||||
base = make_mult_expr(base, lwid);
|
||||
base = make_add_expr(base, loff);
|
||||
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);
|
||||
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);
|
||||
} 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;
|
||||
}
|
||||
|
||||
|
|
@ -802,9 +845,10 @@ NetExpr* condition_reduce(NetExpr*expr)
|
|||
}
|
||||
|
||||
static NetExpr* do_elab_and_eval(Design*des, NetScope*scope, PExpr*pe,
|
||||
int context_width, bool need_const, bool annotatable,
|
||||
bool force_expand,
|
||||
ivl_variable_type_t cast_type)
|
||||
int context_width, bool need_const,
|
||||
bool annotatable, bool force_expand,
|
||||
ivl_variable_type_t cast_type,
|
||||
bool force_unsigned)
|
||||
{
|
||||
PExpr::width_mode_t mode = PExpr::SIZED;
|
||||
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))
|
||||
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) {
|
||||
cerr << pe->get_fileline() << ": elab_and_eval: test_width of "
|
||||
<< *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,
|
||||
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,
|
||||
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
|
||||
* 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.
|
||||
*/
|
||||
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)
|
||||
{
|
||||
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,
|
||||
|
|
@ -1392,8 +1443,8 @@ bool evaluate_index_prefix(Design*des, NetScope*scope,
|
|||
{
|
||||
list<index_component_t>::const_iterator icur = indices.begin();
|
||||
for (size_t idx = 0 ; (idx+1) < indices.size() ; idx += 1, ++icur) {
|
||||
assert(icur != indices.end());
|
||||
assert(icur->sel == index_component_t::SEL_BIT);
|
||||
ivl_assert(*(icur->msb), icur != indices.end());
|
||||
ivl_assert(*(icur->msb), icur->sel == index_component_t::SEL_BIT);
|
||||
NetExpr*texpr = elab_and_eval(des, scope, icur->msb, -1, true);
|
||||
|
||||
long tmp;
|
||||
|
|
@ -1404,7 +1455,7 @@ bool evaluate_index_prefix(Design*des, NetScope*scope,
|
|||
return false;
|
||||
}
|
||||
|
||||
prefix_indices .push_back(tmp);
|
||||
prefix_indices.push_back(tmp);
|
||||
delete texpr;
|
||||
}
|
||||
|
||||
|
|
|
|||
38
netmisc.h
38
netmisc.h
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef 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
|
||||
* 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
|
||||
* with V0 until the expression has the desired width. This may mean
|
||||
* not transforming the expression at all, if it is already wide
|
||||
* enough.
|
||||
* This function transforms an expression by either zero or sign extending
|
||||
* the high bits until the expression has the desired width. This may mean
|
||||
* not transforming the expression at all, if it is already wide 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,
|
||||
const LineInfo&info);
|
||||
|
||||
|
|
@ -258,7 +278,8 @@ extern NetExpr* elab_and_eval(Design*des, NetScope*scope,
|
|||
PExpr*pe, int context_width,
|
||||
bool need_const =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,
|
||||
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_variable_type_t lv_type,
|
||||
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,
|
||||
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
|
||||
* 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 {
|
||||
-- icur;
|
||||
acc_wid *= pcur->width();
|
||||
-- pcur;
|
||||
if (pcur->get_msb() >= pcur->get_lsb())
|
||||
acc_off += (*icur - pcur->get_lsb()) * acc_wid;
|
||||
else
|
||||
acc_off += (pcur->get_lsb() - *icur) * acc_wid;
|
||||
|
||||
-- pcur;
|
||||
|
||||
} while (icur != prefix.begin());
|
||||
|
||||
// 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
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -24,21 +24,20 @@
|
|||
# include "netmisc.h"
|
||||
|
||||
|
||||
/*
|
||||
* This function transforms an expression by padding the high bits
|
||||
* 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)
|
||||
NetExpr*pad_to_width(NetExpr*expr, unsigned wid, bool signed_flag,
|
||||
const LineInfo&info)
|
||||
{
|
||||
if (wid <= expr->expr_width())
|
||||
if (wid <= expr->expr_width()) {
|
||||
expr->cast_signed(signed_flag);
|
||||
return expr;
|
||||
}
|
||||
|
||||
/* If the expression is a const, then replace it with a wider
|
||||
const. This is a more efficient result. */
|
||||
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->set_line(info);
|
||||
delete expr;
|
||||
|
|
@ -46,8 +45,30 @@ NetExpr*pad_to_width(NetExpr*expr, unsigned wid, const LineInfo&info)
|
|||
}
|
||||
|
||||
NetESelect*tmp = new NetESelect(expr, 0, wid);
|
||||
tmp->cast_signed(signed_flag);
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
|||
390
parse.y
390
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)
|
||||
*
|
||||
* 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 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)
|
||||
{
|
||||
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 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*> >;
|
||||
tmp->push_back(make_pair(lex_strings.make(id), expr));
|
||||
list<pform_port_t>*tmp = new list<pform_port_t>;
|
||||
tmp->push_back(pform_port_t(lex_strings.make(id), udims, expr));
|
||||
delete[]id;
|
||||
return tmp;
|
||||
}
|
||||
static list<pair<perm_string,PExpr*> >* make_port_list(list<pair<perm_string, PExpr*> >*tmp,
|
||||
char*id, PExpr*expr)
|
||||
static list<pform_port_t>* make_port_list(list<pform_port_t>*tmp,
|
||||
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;
|
||||
return tmp;
|
||||
}
|
||||
|
|
@ -370,7 +374,7 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
|
|||
char*text;
|
||||
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;
|
||||
|
||||
|
|
@ -452,6 +456,8 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
|
|||
|
||||
PSpecPath* specpath;
|
||||
list<index_component_t> *dimensions;
|
||||
|
||||
LexicalScope::lifetime_t lifetime;
|
||||
};
|
||||
|
||||
%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 <flag> signing unsigned_signed_opt signed_unsigned_opt
|
||||
%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 <drive> drive_strength drive_strength_opt dr_strength0 dr_strength1
|
||||
%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 <perm_strings> register_variable_list net_variable_list event_variable_list
|
||||
%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
|
||||
|
||||
|
|
@ -607,7 +613,8 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
|
|||
%type <gates> gate_instance_list
|
||||
|
||||
%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> inc_or_dec_expression inside_expression lpvalue
|
||||
%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> dimensions_opt dimensions
|
||||
|
||||
%type <nettype> net_type var_type net_type_opt
|
||||
%type <nettype> net_type net_type_opt
|
||||
%type <gatetype> gatetype switchtype
|
||||
%type <porttype> port_direction port_direction_opt
|
||||
%type <vartype> bit_logic bit_logic_opt
|
||||
|
|
@ -648,6 +655,7 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
|
|||
%type <statement> statement statement_item statement_or_null
|
||||
%type <statement> compressed_statement
|
||||
%type <statement> loop_statement for_step jump_statement
|
||||
%type <statement> procedural_assertion_statement
|
||||
%type <statement_list> statement_or_null_list statement_or_null_list_opt
|
||||
|
||||
%type <statement> analog_statement
|
||||
|
|
@ -664,6 +672,8 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
|
|||
%type <int_val> atom2_type
|
||||
%type <int_val> module_start module_end
|
||||
|
||||
%type <lifetime> lifetime lifetime_opt
|
||||
|
||||
%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_XOR_EQ K_LS_EQ K_RS_EQ K_RSS_EQ
|
||||
|
|
@ -723,17 +733,17 @@ block_identifier_opt /* */
|
|||
;
|
||||
|
||||
class_declaration /* IEEE1800-2005: A.1.2 */
|
||||
: K_virtual_opt K_class class_identifier class_declaration_extends_opt ';'
|
||||
{ pform_start_class_declaration(@2, $3, $4.type, $4.exprs); }
|
||||
: K_virtual_opt K_class lifetime_opt class_identifier class_declaration_extends_opt ';'
|
||||
{ pform_start_class_declaration(@2, $4, $5.type, $5.exprs, $3); }
|
||||
class_items_opt K_endclass
|
||||
{ // Process a class.
|
||||
pform_end_class_declaration(@8);
|
||||
pform_end_class_declaration(@9);
|
||||
}
|
||||
class_declaration_endlabel_opt
|
||||
{ // Wrap up the class.
|
||||
if ($10 && $3 && $3->name != $10) {
|
||||
yyerror(@10, "error: Class end label doesn't match class name.");
|
||||
delete[]$10;
|
||||
if ($11 && $4 && $4->name != $11) {
|
||||
yyerror(@11, "error: Class end label doesn't match class name.");
|
||||
delete[]$11;
|
||||
}
|
||||
}
|
||||
;
|
||||
|
|
@ -1193,7 +1203,7 @@ for_step /* IEEE1800-2005: A.6.8 */
|
|||
definitions in the func_body to take on the scope of the function
|
||||
instead of the module. */
|
||||
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);
|
||||
current_function = pform_push_function_scope(@1, $4, $2);
|
||||
}
|
||||
|
|
@ -1214,7 +1224,7 @@ function_declaration /* IEEE1800-2005: A.2.6 */
|
|||
"function name");
|
||||
}
|
||||
if (! gn_system_verilog()) {
|
||||
yyerror(@11, "error: Function end label require "
|
||||
yyerror(@11, "error: Function end labels require "
|
||||
"SystemVerilog.");
|
||||
}
|
||||
delete[]$11;
|
||||
|
|
@ -1222,7 +1232,7 @@ function_declaration /* IEEE1800-2005: A.2.6 */
|
|||
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);
|
||||
current_function = pform_push_function_scope(@1, $4, $2);
|
||||
}
|
||||
|
|
@ -1258,7 +1268,7 @@ function_declaration /* IEEE1800-2005: A.2.6 */
|
|||
|
||||
/* 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) {
|
||||
pform_pop_scope();
|
||||
|
|
@ -1364,6 +1374,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_statement /* IEEE1800-2005: A.6.8 */
|
||||
|
|
@ -1407,6 +1427,7 @@ loop_statement /* IEEE1800-2005: A.6.8 */
|
|||
vector<Statement*>tmp_for_list (1);
|
||||
tmp_for_list[0] = tmp_for;
|
||||
PBlock*tmp_blk = current_block_stack.top();
|
||||
current_block_stack.pop();
|
||||
tmp_blk->set_statement(tmp_for_list);
|
||||
$$ = tmp_blk;
|
||||
delete[]$4;
|
||||
|
|
@ -1457,6 +1478,7 @@ loop_statement /* IEEE1800-2005: A.6.8 */
|
|||
vector<Statement*>tmp_for_list(1);
|
||||
tmp_for_list[0] = tmp_for;
|
||||
PBlock*tmp_blk = current_block_stack.top();
|
||||
current_block_stack.pop();
|
||||
tmp_blk->set_statement(tmp_for_list);
|
||||
$$ = tmp_blk;
|
||||
}
|
||||
|
|
@ -1703,20 +1725,20 @@ open_range_list /* IEEE1800-2005 A.2.11 */
|
|||
;
|
||||
|
||||
package_declaration /* IEEE1800-2005 A.1.2 */
|
||||
: K_package IDENTIFIER ';'
|
||||
{ pform_start_package_declaration(@1, $2);
|
||||
: K_package lifetime_opt IDENTIFIER ';'
|
||||
{ pform_start_package_declaration(@1, $3, $2);
|
||||
}
|
||||
package_item_list_opt
|
||||
K_endpackage endlabel_opt
|
||||
{ pform_end_package_declaration(@1);
|
||||
// If an end label is present make sure it match the package name.
|
||||
if ($7) {
|
||||
if (strcmp($2,$7) != 0) {
|
||||
yyerror(@7, "error: End label doesn't match package name");
|
||||
if ($8) {
|
||||
if (strcmp($3,$8) != 0) {
|
||||
yyerror(@8, "error: End label doesn't match package name");
|
||||
}
|
||||
delete[]$7;
|
||||
delete[]$8;
|
||||
}
|
||||
delete[]$2;
|
||||
delete[]$3;
|
||||
}
|
||||
;
|
||||
|
||||
|
|
@ -1794,6 +1816,21 @@ property_expr /* IEEE1800-2012 A.2.10 */
|
|||
: expression
|
||||
;
|
||||
|
||||
procedural_assertion_statement /* IEEE1800-2012 A.6.10 */
|
||||
: K_assert '(' expression ')' statement %prec less_than_K_else
|
||||
{ yyerror(@1, "sorry: Simple immediate assertion statements not implemented.");
|
||||
$$ = 0;
|
||||
}
|
||||
| K_assert '(' expression ')' K_else statement
|
||||
{ yyerror(@1, "sorry: Simple immediate assertion statements not implemented.");
|
||||
$$ = 0;
|
||||
}
|
||||
| K_assert '(' expression ')' statement K_else statement
|
||||
{ yyerror(@1, "sorry: Simple immediate assertion statements not implemented.");
|
||||
$$ = 0;
|
||||
}
|
||||
;
|
||||
|
||||
/* The property_qualifier rule is as literally described in the LRM,
|
||||
but the use is usually as { property_qualifier }, which is
|
||||
implemented by the property_qualifier_opt rule below. */
|
||||
|
|
@ -1895,7 +1932,7 @@ streaming_concatenation /* IEEE1800-2005: A.8.1 */
|
|||
|
||||
task_declaration /* IEEE1800-2005: A.2.7 */
|
||||
|
||||
: K_task K_automatic_opt IDENTIFIER ';'
|
||||
: K_task lifetime_opt IDENTIFIER ';'
|
||||
{ assert(current_task == 0);
|
||||
current_task = pform_push_task_scope(@1, $3, $2);
|
||||
}
|
||||
|
|
@ -1908,7 +1945,7 @@ task_declaration /* IEEE1800-2005: A.2.7 */
|
|||
pform_pop_scope();
|
||||
current_task = 0;
|
||||
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;
|
||||
}
|
||||
|
|
@ -1931,7 +1968,7 @@ task_declaration /* IEEE1800-2005: A.2.7 */
|
|||
delete[]$3;
|
||||
}
|
||||
|
||||
| K_task K_automatic_opt IDENTIFIER '('
|
||||
| K_task lifetime_opt IDENTIFIER '('
|
||||
{ assert(current_task == 0);
|
||||
current_task = pform_push_task_scope(@1, $3, $2);
|
||||
}
|
||||
|
|
@ -1965,7 +2002,7 @@ task_declaration /* IEEE1800-2005: A.2.7 */
|
|||
delete[]$3;
|
||||
}
|
||||
|
||||
| K_task K_automatic_opt IDENTIFIER '(' ')' ';'
|
||||
| K_task lifetime_opt IDENTIFIER '(' ')' ';'
|
||||
{ assert(current_task == 0);
|
||||
current_task = pform_push_task_scope(@1, $3, $2);
|
||||
}
|
||||
|
|
@ -1982,7 +2019,7 @@ task_declaration /* IEEE1800-2005: A.2.7 */
|
|||
pform_pop_scope();
|
||||
current_task = 0;
|
||||
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;
|
||||
}
|
||||
|
|
@ -2005,7 +2042,7 @@ task_declaration /* IEEE1800-2005: A.2.7 */
|
|||
delete[]$3;
|
||||
}
|
||||
|
||||
| K_task K_automatic_opt IDENTIFIER error K_endtask
|
||||
| K_task lifetime_opt IDENTIFIER error K_endtask
|
||||
{
|
||||
assert(current_task == 0);
|
||||
}
|
||||
|
|
@ -2213,7 +2250,7 @@ variable_dimension /* IEEE1800-2005: A.2.5 */
|
|||
}
|
||||
| '[' expression ']'
|
||||
{ // SystemVerilog canonical range
|
||||
if (generation_flag < GN_VER2005_SV) {
|
||||
if (!gn_system_verilog()) {
|
||||
warn_count += 1;
|
||||
cerr << @2 << ": warning: Use of SystemVerilog [size] dimension. "
|
||||
<< "Use at least -g2005-sv to remove this warning." << endl;
|
||||
|
|
@ -2243,6 +2280,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
|
||||
variety of different objects. The syntax inside the (* *) is a
|
||||
comma separated list of names or names with assigned values. */
|
||||
|
|
@ -2317,10 +2367,20 @@ block_item_decl
|
|||
{ 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 ';'
|
||||
{ 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 ';'
|
||||
{ if ($2) pform_make_events($2, @1.text, @1.first_line);
|
||||
}
|
||||
|
|
@ -3033,7 +3093,7 @@ branch_probe_expression
|
|||
;
|
||||
|
||||
expression
|
||||
: expr_primary
|
||||
: expr_primary_or_typename
|
||||
{ $$ = $1; }
|
||||
| inc_or_dec_expression
|
||||
{ $$ = $1; }
|
||||
|
|
@ -3328,6 +3388,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
|
||||
: number
|
||||
{ assert($1);
|
||||
|
|
@ -3369,15 +3443,6 @@ expr_primary
|
|||
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
|
||||
indexed arrays and part selects */
|
||||
|
||||
|
|
@ -3681,12 +3746,11 @@ expr_primary
|
|||
|
||||
/* Cast expressions are primaries */
|
||||
|
||||
| DEC_NUMBER '\'' '(' expression ')'
|
||||
| expr_primary '\'' '(' expression ')'
|
||||
{ PExpr*base = $4;
|
||||
if (gn_system_verilog()) {
|
||||
PECastSize*tmp = new PECastSize($1->as_ulong(), base);
|
||||
PECastSize*tmp = new PECastSize($1, base);
|
||||
FILE_NAME(tmp, @1);
|
||||
delete $1;
|
||||
$$ = tmp;
|
||||
} else {
|
||||
yyerror(@1, "error: Size cast requires SystemVerilog.");
|
||||
|
|
@ -4002,14 +4066,21 @@ list_of_identifiers
|
|||
;
|
||||
|
||||
list_of_port_identifiers
|
||||
: IDENTIFIER
|
||||
{ $$ = make_port_list($1, 0); }
|
||||
| IDENTIFIER '=' expression
|
||||
{ $$ = make_port_list($1, $3); }
|
||||
| list_of_port_identifiers ',' IDENTIFIER
|
||||
{ $$ = make_port_list($1, $3, 0); }
|
||||
| list_of_port_identifiers ',' IDENTIFIER '=' expression
|
||||
{ $$ = make_port_list($1, $3, $5); }
|
||||
: IDENTIFIER dimensions_opt
|
||||
{ $$ = make_port_list($1, $2, 0); }
|
||||
| list_of_port_identifiers ',' IDENTIFIER dimensions_opt
|
||||
{ $$ = make_port_list($1, $3, $4, 0); }
|
||||
;
|
||||
|
||||
list_of_variable_port_identifiers
|
||||
: 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 +4289,7 @@ port_declaration
|
|||
port_declaration_context.port_net_type = use_type;
|
||||
port_declaration_context.data_type = $4;
|
||||
|
||||
pform_make_reginit(@5, name, $7);
|
||||
pform_make_var_init(@5, name, $7);
|
||||
|
||||
delete[]$5;
|
||||
$$ = ptmp;
|
||||
|
|
@ -4372,13 +4443,13 @@ local_timeunit_prec_decl2
|
|||
items, and finally an end marker. */
|
||||
|
||||
module
|
||||
: attribute_list_opt module_start IDENTIFIER
|
||||
{ pform_startmodule(@2, $3, $2==K_program, $2==K_interface, $1); }
|
||||
: attribute_list_opt module_start lifetime_opt IDENTIFIER
|
||||
{ pform_startmodule(@2, $4, $2==K_program, $2==K_interface, $3, $1); }
|
||||
module_package_import_list_opt
|
||||
module_parameter_port_list_opt
|
||||
module_port_list_opt
|
||||
module_attribute_foreign ';'
|
||||
{ pform_module_set_ports($7); }
|
||||
{ pform_module_set_ports($8); }
|
||||
local_timeunit_prec_decl_opt
|
||||
{ have_timeunit_decl = true; // Every thing past here is
|
||||
have_timeprec_decl = true; // a check!
|
||||
|
|
@ -4404,22 +4475,22 @@ module
|
|||
}
|
||||
// Check that program/endprogram and module/endmodule
|
||||
// keywords match.
|
||||
if ($2 != $14) {
|
||||
if ($2 != $15) {
|
||||
switch ($2) {
|
||||
case K_module:
|
||||
yyerror(@14, "error: module not closed by endmodule.");
|
||||
yyerror(@15, "error: module not closed by endmodule.");
|
||||
break;
|
||||
case K_program:
|
||||
yyerror(@14, "error: program not closed by endprogram.");
|
||||
yyerror(@15, "error: program not closed by endprogram.");
|
||||
break;
|
||||
case K_interface:
|
||||
yyerror(@14, "error: interface not closed by endinterface.");
|
||||
yyerror(@15, "error: interface not closed by endinterface.");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
pform_endmodule($3, in_celldefine, ucd);
|
||||
pform_endmodule($4, in_celldefine, ucd);
|
||||
have_timeunit_decl = false; // We will allow decls again.
|
||||
have_timeprec_decl = false;
|
||||
}
|
||||
|
|
@ -4429,19 +4500,19 @@ module
|
|||
// endlabel_opt but still have the pform_endmodule() called
|
||||
// early enough that the lexor can know we are outside the
|
||||
// module.
|
||||
if ($16) {
|
||||
if (strcmp($3,$16) != 0) {
|
||||
if ($17) {
|
||||
if (strcmp($4,$17) != 0) {
|
||||
switch ($2) {
|
||||
case K_module:
|
||||
yyerror(@16, "error: End label doesn't match "
|
||||
yyerror(@17, "error: End label doesn't match "
|
||||
"module name.");
|
||||
break;
|
||||
case K_program:
|
||||
yyerror(@16, "error: End label doesn't match "
|
||||
yyerror(@17, "error: End label doesn't match "
|
||||
"program name.");
|
||||
break;
|
||||
case K_interface:
|
||||
yyerror(@16, "error: End label doesn't match "
|
||||
yyerror(@17, "error: End label doesn't match "
|
||||
"interface name.");
|
||||
break;
|
||||
default:
|
||||
|
|
@ -4452,9 +4523,9 @@ module
|
|||
yyerror(@8, "error: Module end labels require "
|
||||
"SystemVerilog.");
|
||||
}
|
||||
delete[]$16;
|
||||
delete[]$17;
|
||||
}
|
||||
delete[]$3;
|
||||
delete[]$4;
|
||||
}
|
||||
;
|
||||
|
||||
|
|
@ -4597,58 +4668,102 @@ module_item
|
|||
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>;
|
||||
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 ';'
|
||||
{ pform_makewire(@2, $5, $4, $6, $3, $2, IVL_VT_NO_TYPE, $1, SR_BOTH); }
|
||||
| attribute_list_opt port_direction net_type data_type_or_implicit list_of_port_identifiers ';'
|
||||
{ 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 ';'
|
||||
{ list<pair<perm_string,PExpr*> >::const_iterator pp;
|
||||
list<perm_string>*tmp = new list<perm_string>;
|
||||
for (pp = $6->begin(); pp != $6->end(); ++ pp ) {
|
||||
tmp->push_back((*pp).first);
|
||||
| attribute_list_opt port_direction K_wreal list_of_port_identifiers ';'
|
||||
{ real_type_t*real_type = new real_type_t(real_type_t::REAL);
|
||||
pform_module_define_port(@2, $4, $2, NetNet::WIRE, real_type, $1);
|
||||
}
|
||||
|
||||
/* The next three rules handle port declarations that include a variable
|
||||
type, e.g.
|
||||
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;
|
||||
}
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
| attribute_list_opt K_input 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;
|
||||
}
|
||||
delete $6;
|
||||
if (use_type == NetNet::NONE)
|
||||
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 port_direction K_wreal list_of_identifiers ';'
|
||||
{ pform_makewire(@2, 0, true, $4, NetNet::WIRE, $2,
|
||||
IVL_VT_REAL, $1, SR_BOTH);
|
||||
| attribute_list_opt K_output data_type_or_implicit list_of_variable_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;
|
||||
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);
|
||||
}
|
||||
|
||||
/* var_type declaration (reg variables) cannot be input or output,
|
||||
because the port declaration implies an external driver, which
|
||||
cannot be attached to a reg. These rules catch that error early. */
|
||||
|
||||
| attribute_list_opt K_input var_type unsigned_signed_opt dimensions_opt list_of_identifiers ';'
|
||||
{ pform_makewire(@2, $5, $4, $6, $3, NetNet::PINPUT,
|
||||
IVL_VT_NO_TYPE, $1);
|
||||
yyerror(@3, "error: reg variables cannot be inputs.");
|
||||
}
|
||||
|
||||
| attribute_list_opt K_inout var_type unsigned_signed_opt dimensions_opt list_of_identifiers ';'
|
||||
{ pform_makewire(@2, $5, $4, $6, $3, NetNet::PINOUT,
|
||||
IVL_VT_NO_TYPE, $1);
|
||||
yyerror(@3, "error: reg variables cannot be inouts.");
|
||||
}
|
||||
|
||||
| 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.");
|
||||
if ($1) delete $1;
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
@ -5048,10 +5163,6 @@ net_type
|
|||
| K_uwire { $$ = NetNet::UNRESOLVED_WIRE; }
|
||||
;
|
||||
|
||||
var_type
|
||||
: K_reg { $$ = NetNet::REG; }
|
||||
;
|
||||
|
||||
param_type
|
||||
: bit_logic_opt unsigned_signed_opt dimensions_opt
|
||||
{ param_active_range = $3;
|
||||
|
|
@ -5477,11 +5588,17 @@ register_variable
|
|||
$$ = $1;
|
||||
}
|
||||
| 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,
|
||||
NetNet::NOT_A_PORT, IVL_VT_NO_TYPE, 0);
|
||||
pform_set_reg_idx(name, $2);
|
||||
pform_make_reginit(@1, name, $4);
|
||||
pform_make_var_init(@1, name, $4);
|
||||
$$ = $1;
|
||||
}
|
||||
;
|
||||
|
|
@ -5734,7 +5851,23 @@ specify_path_identifiers
|
|||
delete[]$1;
|
||||
}
|
||||
| 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;
|
||||
delete[]$1;
|
||||
|
|
@ -5746,7 +5879,23 @@ specify_path_identifiers
|
|||
delete[]$3;
|
||||
}
|
||||
| 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;
|
||||
delete[]$3;
|
||||
|
|
@ -6094,6 +6243,8 @@ statement_item /* This is roughly statement_item in the LRM */
|
|||
$$ = tmp;
|
||||
}
|
||||
|
||||
| procedural_assertion_statement { $$ = $1; }
|
||||
|
||||
| loop_statement { $$ = $1; }
|
||||
|
||||
| jump_statement { $$ = $1; }
|
||||
|
|
@ -6777,7 +6928,6 @@ udp_primitive
|
|||
presence is significant. This is a fairly common pattern so
|
||||
collect those rules here. */
|
||||
|
||||
K_automatic_opt: K_automatic { $$ = true; } | { $$ = false; } ;
|
||||
K_packed_opt : K_packed { $$ = true; } | { $$ = false; } ;
|
||||
K_reg_opt : K_reg { $$ = true; } | { $$ = false; } ;
|
||||
K_static_opt : K_static { $$ = true; } | { $$ = false; } ;
|
||||
|
|
|
|||
496
pform.cc
496
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)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
|
|
@ -40,6 +40,7 @@
|
|||
# include <sstream>
|
||||
# include <cstring>
|
||||
# include <cstdlib>
|
||||
# include <cctype>
|
||||
|
||||
# include "ivl_assert.h"
|
||||
# include "ivl_alloc.h"
|
||||
|
|
@ -86,6 +87,42 @@ std::string vlltype::get_fileline() const
|
|||
|
||||
}
|
||||
|
||||
static bool is_hex_digit_str(const char *str)
|
||||
{
|
||||
while (*str) {
|
||||
if (!isxdigit(*str)) return false;
|
||||
str++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool is_dec_digit_str(const char *str)
|
||||
{
|
||||
while (*str) {
|
||||
if (!isdigit(*str)) return false;
|
||||
str++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool is_oct_digit_str(const char *str)
|
||||
{
|
||||
while (*str) {
|
||||
if (*str < '0' || *str > '7') return false;
|
||||
str++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool is_bin_digit_str(const char *str)
|
||||
{
|
||||
while (*str) {
|
||||
if (*str != '0' && *str != '1') return false;
|
||||
str++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse configuration file with format <key>=<value>, where key
|
||||
* is the hierarchical name of a valid parameter name, and value
|
||||
|
|
@ -152,90 +189,137 @@ void parm_to_defparam_list(const string¶m)
|
|||
ptr = strchr(nkey, '.');
|
||||
}
|
||||
name.push_back(name_component_t(lex_strings.make(nkey)));
|
||||
free(key);
|
||||
|
||||
// Resolve value to PExpr class. Should support all kind of constant
|
||||
// format including based number, dec number, real number and string.
|
||||
if (*value == '"') { // string type
|
||||
char *buf = strdup (value);
|
||||
char *buf_ptr = buf+1;
|
||||
// Parse until another '"' or '\0'
|
||||
while (*buf_ptr != '"' && *buf_ptr != '\0') {
|
||||
buf_ptr++;
|
||||
// Check for escape, especially '\"', which does not mean the
|
||||
// end of string.
|
||||
if (*buf_ptr == '\\' && *(buf_ptr+1) != '\0')
|
||||
buf_ptr += 2;
|
||||
}
|
||||
if (*buf_ptr == '\0') // String end without '"'
|
||||
cerr << "<command line>: error: missing close quote of string for defparam: " << name << endl;
|
||||
else if (*(buf_ptr+1) != 0) { // '"' appears within string with no escape
|
||||
cerr << buf_ptr << endl;
|
||||
cerr << "<command line>: error: \'\"\' appears within string value for defparam: " << name
|
||||
<< ". Ignore characters after \'\"\'" << endl;
|
||||
}
|
||||
|
||||
*buf_ptr = '\0';
|
||||
buf_ptr = buf+1;
|
||||
// Remember to use 'new' to allocate string for PEString
|
||||
// because 'delete' is used by its destructor.
|
||||
char *nchar = strcpy(new char [strlen(buf_ptr)+1], buf_ptr);
|
||||
PExpr* ndec = new PEString(nchar);
|
||||
// Is it a string?
|
||||
if (*value == '"') {
|
||||
char *buf = strdup (value);
|
||||
char *buf_ptr = buf+1;
|
||||
// Parse until another '"' or '\0'
|
||||
while (*buf_ptr != '"' && *buf_ptr != '\0') {
|
||||
buf_ptr++;
|
||||
// Check for escape, especially '\"', which does not mean the
|
||||
// end of string.
|
||||
if (*buf_ptr == '\\' && *(buf_ptr+1) != '\0')
|
||||
buf_ptr += 2;
|
||||
}
|
||||
if (*buf_ptr == '\0') // String end without '"'
|
||||
cerr << "<command line>: error: missing close quote of string for defparam: " << name << endl;
|
||||
else if (*(buf_ptr+1) != 0) { // '"' appears within string with no escape
|
||||
cerr << buf_ptr << endl;
|
||||
cerr << "<command line>: error: \'\"\' appears within string value for defparam: " << name
|
||||
<< ". Ignore characters after \'\"\'" << endl;
|
||||
}
|
||||
|
||||
*buf_ptr = '\0';
|
||||
buf_ptr = buf+1;
|
||||
// Remember to use 'new' to allocate string for PEString
|
||||
// because 'delete' is used by its destructor.
|
||||
char *nchar = strcpy(new char [strlen(buf_ptr)+1], buf_ptr);
|
||||
PExpr* ndec = new PEString(nchar);
|
||||
Module::user_defparms.push_back( make_pair(name, ndec) );
|
||||
free(buf);
|
||||
free(buf);
|
||||
free(value);
|
||||
return;
|
||||
}
|
||||
else { // number type
|
||||
char *num = strchr(value, '\'');
|
||||
if (num != 0) {
|
||||
verinum *val;
|
||||
// BASED_NUMBER, something like - scope.parameter='b11
|
||||
// make sure to check 'h' first because 'b'&'d' may be included
|
||||
// in hex format
|
||||
if (strchr(num, 'h') || strchr(num, 'H'))
|
||||
val = make_unsized_hex(num);
|
||||
else if (strchr(num, 'd') || strchr(num, 'D'))
|
||||
if (strchr(num, 'x') || strchr(num, 'X') || strchr(num, 'z') || strchr(num, 'Z'))
|
||||
val = make_undef_highz_dec(num);
|
||||
else
|
||||
val = make_unsized_dec(num);
|
||||
else if (strchr(num, 'b') || strchr(num, 'B')) {
|
||||
val = make_unsized_binary(num);
|
||||
}
|
||||
else if (strchr(num, 'o') || strchr(num, 'O'))
|
||||
val = make_unsized_octal(num);
|
||||
else {
|
||||
cerr << "<command line>: error: value specify error for defparam: " << name << endl;
|
||||
free(key);
|
||||
free(value);
|
||||
return;
|
||||
}
|
||||
|
||||
// BASED_NUMBER with size, something like - scope.parameter=2'b11
|
||||
if (num != value) {
|
||||
*num = 0;
|
||||
verinum *siz = make_unsized_dec(value);
|
||||
val = pform_verinum_with_size(siz, val, "<command line>", 0);
|
||||
}
|
||||
|
||||
PExpr* ndec = new PENumber(val);
|
||||
Module::user_defparms.push_back( make_pair(name, ndec) );
|
||||
|
||||
}
|
||||
else {
|
||||
// REALTIME, something like - scope.parameter=1.22 or scope.parameter=1e2
|
||||
if (strchr(value, '.') || strchr(value, 'e') || strchr(value, 'E')) {
|
||||
verireal *val = new verireal(value);
|
||||
PExpr* nreal = new PEFNumber(val);
|
||||
Module::user_defparms.push_back( make_pair(name, nreal) );
|
||||
}
|
||||
else {
|
||||
// DEC_NUMBER, something like - scope.parameter=3
|
||||
verinum *val = make_unsized_dec(value);
|
||||
PExpr* ndec = new PENumber(val);
|
||||
Module::user_defparms.push_back( make_pair(name, ndec) );
|
||||
}
|
||||
}
|
||||
// Is it a based number?
|
||||
char *num = strchr(value, '\'');
|
||||
if (num != 0) {
|
||||
verinum *val;
|
||||
const char *base = num + 1;
|
||||
if (*base == 's' || *base == 'S')
|
||||
base++;
|
||||
switch (*base) {
|
||||
case 'h':
|
||||
case 'H':
|
||||
if (is_hex_digit_str(base+1)) {
|
||||
val = make_unsized_hex(num);
|
||||
} else {
|
||||
cerr << "<command line>: error: invalid digit in hex value specified for defparam: " << name << endl;
|
||||
free(value);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 'd':
|
||||
case 'D':
|
||||
if (is_dec_digit_str(base+1)) {
|
||||
val = make_unsized_dec(num);
|
||||
} else {
|
||||
cerr << "<command line>: error: invalid digit in decimal value specified for defparam: " << name << endl;
|
||||
free(value);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 'o':
|
||||
case 'O':
|
||||
if (is_oct_digit_str(base+1)) {
|
||||
val = make_unsized_octal(num);
|
||||
} else {
|
||||
cerr << "<command line>: error: invalid digit in octal value specified for defparam: " << name << endl;
|
||||
free(value);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 'b':
|
||||
case 'B':
|
||||
if (is_bin_digit_str(base+1)) {
|
||||
val = make_unsized_binary(num);
|
||||
} else {
|
||||
cerr << "<command line>: error: invalid digit in binary value specified for defparam: " << name << endl;
|
||||
free(value);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
cerr << "<command line>: error: invalid numeric base specified for defparam: " << name << endl;
|
||||
free(value);
|
||||
return;
|
||||
}
|
||||
if (num != value) { // based number with size
|
||||
*num = 0;
|
||||
if (is_dec_digit_str(value)) {
|
||||
verinum *siz = make_unsized_dec(value);
|
||||
val = pform_verinum_with_size(siz, val, "<command line>", 0);
|
||||
} else {
|
||||
cerr << "<command line>: error: invalid size for value specified for defparam: " << name << endl;
|
||||
free(value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
PExpr* ndec = new PENumber(val);
|
||||
Module::user_defparms.push_back( make_pair(name, ndec) );
|
||||
free(value);
|
||||
return;
|
||||
}
|
||||
free(key);
|
||||
|
||||
// Is it a decimal number?
|
||||
num = (value[0] == '-') ? value + 1 : value;
|
||||
if (is_dec_digit_str(num)) {
|
||||
verinum *val = make_unsized_dec(num);
|
||||
if (value[0] == '-') *val = -(*val);
|
||||
PExpr* ndec = new PENumber(val);
|
||||
Module::user_defparms.push_back( make_pair(name, ndec) );
|
||||
free(value);
|
||||
return;
|
||||
}
|
||||
|
||||
// Is it a real number?
|
||||
char *end = 0;
|
||||
double rval = strtod(value, &end);
|
||||
if (end != value && *end == 0) {
|
||||
verireal *val = new verireal(rval);
|
||||
PExpr* nreal = new PEFNumber(val);
|
||||
Module::user_defparms.push_back( make_pair(name, nreal) );
|
||||
free(value);
|
||||
return;
|
||||
}
|
||||
|
||||
// None of the above.
|
||||
cerr << "<command line>: error: invalid value specified for defparam: " << name << endl;
|
||||
free(value);
|
||||
}
|
||||
|
||||
|
|
@ -312,12 +396,29 @@ static inline void FILE_NAME(LineInfo*obj, const char*file, unsigned lineno)
|
|||
*/
|
||||
static LexicalScope* lexical_scope = 0;
|
||||
|
||||
LexicalScope* pform_peek_scope(void)
|
||||
{
|
||||
assert(lexical_scope);
|
||||
return lexical_scope;
|
||||
}
|
||||
|
||||
void pform_pop_scope()
|
||||
{
|
||||
assert(lexical_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)
|
||||
{
|
||||
PScopeExtra*scopex = dynamic_cast<PScopeExtra*> (scope);
|
||||
|
|
@ -328,17 +429,37 @@ static PScopeExtra* find_nearest_scopex(LexicalScope*scope)
|
|||
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);
|
||||
return lexical_scope;
|
||||
scope->time_unit = pform_time_unit;
|
||||
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);
|
||||
class_scope->default_lifetime = find_lifetime(lifetime);
|
||||
FILE_NAME(class_scope, loc);
|
||||
|
||||
pform_set_scope_timescale(class_scope, loc);
|
||||
|
||||
PScopeExtra*scopex = find_nearest_scopex(lexical_scope);
|
||||
|
||||
assert(!pform_cur_generate);
|
||||
|
|
@ -364,22 +485,33 @@ PClass* pform_push_class_scope(const struct vlltype&loc, perm_string name)
|
|||
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);
|
||||
pkg_scope->default_lifetime = find_lifetime(lifetime);
|
||||
FILE_NAME(pkg_scope, loc);
|
||||
|
||||
pform_set_scope_timescale(pkg_scope, loc);
|
||||
|
||||
lexical_scope = 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);
|
||||
|
||||
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);
|
||||
task->default_lifetime = default_lifetime;
|
||||
FILE_NAME(task, loc);
|
||||
|
||||
pform_set_scope_timescale(task, loc);
|
||||
|
||||
PScopeExtra*scopex = find_nearest_scopex(lexical_scope);
|
||||
if ((scopex == 0) && !gn_system_verilog()) {
|
||||
cerr << task->get_fileline() << ": error: task declarations "
|
||||
|
|
@ -424,15 +556,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,
|
||||
bool is_auto)
|
||||
LexicalScope::lifetime_t lifetime)
|
||||
{
|
||||
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);
|
||||
func->default_lifetime = default_lifetime;
|
||||
FILE_NAME(func, loc);
|
||||
|
||||
pform_set_scope_timescale(func, loc);
|
||||
|
||||
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 "
|
||||
"must be contained within a module." << endl;
|
||||
error_count += 1;
|
||||
|
|
@ -489,6 +627,7 @@ PBlock* pform_push_block_scope(char*name, PBlock::BL_TYPE bt)
|
|||
}
|
||||
|
||||
PBlock*block = new PBlock(block_name, lexical_scope, bt);
|
||||
block->default_lifetime = find_lifetime(LexicalScope::INHERITED);
|
||||
lexical_scope = block;
|
||||
|
||||
return block;
|
||||
|
|
@ -1041,7 +1180,10 @@ void pform_set_timeunit(const char*txt, bool in_module, bool only_check)
|
|||
|
||||
int pform_get_timeunit()
|
||||
{
|
||||
return pform_cur_module.front()->time_unit;
|
||||
if (pform_cur_module.empty())
|
||||
return pform_time_unit;
|
||||
else
|
||||
return pform_cur_module.front()->time_unit;
|
||||
}
|
||||
|
||||
void pform_set_timeprecision(const char*txt, bool in_module, bool only_check)
|
||||
|
|
@ -1131,6 +1273,7 @@ verinum* pform_verinum_with_size(verinum*siz, verinum*val,
|
|||
|
||||
void pform_startmodule(const struct vlltype&loc, const char*name,
|
||||
bool program_block, bool is_interface,
|
||||
LexicalScope::lifetime_t lifetime,
|
||||
list<named_pexpr_t>*attr)
|
||||
{
|
||||
if (! pform_cur_module.empty() && !gn_system_verilog()) {
|
||||
|
|
@ -1139,6 +1282,12 @@ void pform_startmodule(const struct vlltype&loc, const char*name,
|
|||
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 (pform_cur_module.front()->program_block) {
|
||||
cerr << loc << ": error: module, program, or interface "
|
||||
|
|
@ -1158,17 +1307,14 @@ void pform_startmodule(const struct vlltype&loc, const char*name,
|
|||
Module*cur_module = new Module(lexical_scope, lex_name);
|
||||
cur_module->program_block = program_block;
|
||||
cur_module->is_interface = is_interface;
|
||||
/* Set the local time unit/precision to the global value. */
|
||||
cur_module->time_unit = pform_time_unit;
|
||||
cur_module->time_precision = pform_time_prec;
|
||||
cur_module->default_lifetime = find_lifetime(lifetime);
|
||||
|
||||
FILE_NAME(cur_module, loc);
|
||||
|
||||
pform_set_scope_timescale(cur_module, loc);
|
||||
tu_local_flag = tu_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;
|
||||
|
||||
pform_cur_module.push_front(cur_module);
|
||||
|
|
@ -1179,15 +1325,6 @@ void pform_startmodule(const struct vlltype&loc, const char*name,
|
|||
zero. That's just the way it is, thanks to the standard. */
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
@ -1199,7 +1336,7 @@ void pform_startmodule(const struct vlltype&loc, const char*name,
|
|||
void pform_check_timeunit_prec()
|
||||
{
|
||||
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)) {
|
||||
VLerror("error: a timeprecision is missing or is too large!");
|
||||
} else assert(pform_cur_module.front()->time_unit >=
|
||||
|
|
@ -1905,6 +2042,7 @@ static void pform_set_net_range(perm_string name,
|
|||
VLerror("error: name is not a valid net.");
|
||||
return;
|
||||
}
|
||||
|
||||
// If this is not implicit ("implicit" meaning we don't
|
||||
// know what the type is yet) then set the type now.
|
||||
if (net_type != NetNet::IMPLICIT && net_type != NetNet::NONE) {
|
||||
|
|
@ -2000,9 +2138,11 @@ static void pform_makegate(PGBuiltin::Type type,
|
|||
return;
|
||||
}
|
||||
|
||||
for (list<PExpr*>::iterator cur = info.parms->begin()
|
||||
; cur != info.parms->end() ; ++cur) {
|
||||
pform_declare_implicit_nets(*cur);
|
||||
if (info.parms) {
|
||||
for (list<PExpr*>::iterator cur = info.parms->begin()
|
||||
; cur != info.parms->end() ; ++cur) {
|
||||
pform_declare_implicit_nets(*cur);
|
||||
}
|
||||
}
|
||||
|
||||
perm_string dev_name = lex_strings.make(info.name);
|
||||
|
|
@ -2248,23 +2388,30 @@ void pform_make_pgassign_list(list<PExpr*>*alist,
|
|||
}
|
||||
|
||||
/*
|
||||
* this function makes the initial assignment to a register as given
|
||||
* in the source. It handles the case where a reg variable is assigned
|
||||
* where it it declared:
|
||||
* This function makes the initial assignment to a variable as given
|
||||
* in the source. It handles the case where a variable is assigned
|
||||
* where it is declared, e.g.
|
||||
*
|
||||
* 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;
|
||||
* initial foo = <expr>;
|
||||
*
|
||||
* and that is how it is parsed. This syntax is not part of the
|
||||
* IEEE1364-1995 standard, but is approved by OVI as enhancement
|
||||
* BTF-B14.
|
||||
* In SystemVerilog, variable initializations are allowed in any scope.
|
||||
* For static variables, initializations are performed before the start
|
||||
* 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,
|
||||
perm_string name, PExpr*expr)
|
||||
void pform_make_var_init(const struct vlltype&li,
|
||||
perm_string name, PExpr*expr)
|
||||
{
|
||||
if (! pform_at_module_level() && !gn_system_verilog()) {
|
||||
VLerror(li, "error: variable declaration assignments are only "
|
||||
|
|
@ -2275,7 +2422,7 @@ void pform_make_reginit(const struct vlltype&li,
|
|||
|
||||
PWire*cur = pform_get_wire_in_scope(name);
|
||||
if (cur == 0) {
|
||||
VLerror(li, "internal error: reginit to non-register?");
|
||||
VLerror(li, "internal error: var_init to non-register?");
|
||||
delete expr;
|
||||
return;
|
||||
}
|
||||
|
|
@ -2284,10 +2431,8 @@ void pform_make_reginit(const struct vlltype&li,
|
|||
FILE_NAME(lval, li);
|
||||
PAssign*ass = new PAssign(lval, expr, true);
|
||||
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 +2450,8 @@ void pform_module_define_port(const struct vlltype&li,
|
|||
NetNet::PortType port_kind,
|
||||
NetNet::Type type,
|
||||
data_type_t*vtype,
|
||||
list<named_pexpr_t>*attr)
|
||||
list<named_pexpr_t>*attr,
|
||||
bool keep_attr)
|
||||
{
|
||||
struct_type_t*struct_type = 0;
|
||||
ivl_variable_type_t data_type = IVL_VT_NO_TYPE;
|
||||
|
|
@ -2394,10 +2540,37 @@ void pform_module_define_port(const struct vlltype&li,
|
|||
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);
|
||||
}
|
||||
|
||||
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
|
||||
* requested by the parser. The name is unscoped, so I attach the
|
||||
|
|
@ -2591,6 +2764,15 @@ void pform_makewire(const struct vlltype&li,
|
|||
NetNet::Type type,
|
||||
data_type_t*data_type)
|
||||
{
|
||||
if ((lexical_scope == 0) && !gn_system_verilog()) {
|
||||
VLerror(li, "error: variable declarations must be contained within a module.");
|
||||
return;
|
||||
}
|
||||
if (lexical_scope == 0) {
|
||||
VLerror(li, "sorry: variable declarations in the $root scope are not yet supported.");
|
||||
return;
|
||||
}
|
||||
|
||||
list<perm_string>*names = new list<perm_string>;
|
||||
|
||||
for (list<decl_assignment_t*>::iterator cur = assign_list->begin()
|
||||
|
|
@ -2887,6 +3069,14 @@ void pform_set_parameter(const struct vlltype&loc,
|
|||
LexicalScope::range_t*value_range)
|
||||
{
|
||||
LexicalScope*scope = lexical_scope;
|
||||
if ((scope == 0) && !gn_system_verilog()) {
|
||||
VLerror(loc, "error: parameter declarations must be contained within a module.");
|
||||
return;
|
||||
}
|
||||
if (scope == 0) {
|
||||
VLerror(loc, "sorry: parameter declarations in the $root scope are not yet supported.");
|
||||
return;
|
||||
}
|
||||
if (scope == pform_cur_generate) {
|
||||
VLerror("parameter declarations are not permitted in generate blocks");
|
||||
return;
|
||||
|
|
@ -2910,7 +3100,7 @@ void pform_set_parameter(const struct vlltype&loc,
|
|||
error_count += 1;
|
||||
}
|
||||
// Only a Module scope has specparams.
|
||||
if ((dynamic_cast<Module*> (scope)) &&
|
||||
if ((dynamic_cast<Module*> (scope)) &&
|
||||
(scope == pform_cur_module.front()) &&
|
||||
(pform_cur_module.front()->specparams.find(name) !=
|
||||
pform_cur_module.front()->specparams.end())) {
|
||||
|
|
@ -2954,7 +3144,14 @@ void pform_set_localparam(const struct vlltype&loc,
|
|||
bool signed_flag, list<pform_range_t>*range, PExpr*expr)
|
||||
{
|
||||
LexicalScope*scope = lexical_scope;
|
||||
ivl_assert(loc, scope);
|
||||
if ((scope == 0) && !gn_system_verilog()) {
|
||||
VLerror(loc, "error: localparam declarations must be contained within a module.");
|
||||
return;
|
||||
}
|
||||
if (scope == 0) {
|
||||
VLerror(loc, "sorry: localparam declarations in the $root scope are not yet supported.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if the localparam name is already in the dictionary.
|
||||
if (scope->localparams.find(name) != scope->localparams.end()) {
|
||||
|
|
@ -3176,24 +3373,53 @@ static void pform_set_port_type(perm_string name, NetNet::PortType pt,
|
|||
}
|
||||
|
||||
void pform_set_port_type(const struct vlltype&li,
|
||||
list<perm_string>*names,
|
||||
list<pform_range_t>*range,
|
||||
bool signed_flag,
|
||||
list<pform_port_t>*ports,
|
||||
NetNet::PortType pt,
|
||||
data_type_t*dt,
|
||||
list<named_pexpr_t>*attr)
|
||||
{
|
||||
assert(pt != NetNet::PIMPLICIT && pt != NetNet::NOT_A_PORT);
|
||||
|
||||
for (list<perm_string>::iterator cur = names->begin()
|
||||
; cur != names->end() ; ++ cur ) {
|
||||
perm_string txt = *cur;
|
||||
pform_set_port_type(txt, pt, li.text, li.first_line);
|
||||
pform_set_net_range(txt, NetNet::NONE, range, signed_flag, IVL_VT_NO_TYPE,
|
||||
SR_PORT, attr);
|
||||
list<pform_range_t>*range = 0;
|
||||
bool signed_flag = false;
|
||||
if (vector_type_t*vt = dynamic_cast<vector_type_t*> (dt)) {
|
||||
assert(vt->implicit_flag);
|
||||
range = vt->pdims.get();
|
||||
signed_flag = vt->signed_flag;
|
||||
} else {
|
||||
assert(dt == 0);
|
||||
}
|
||||
|
||||
delete names;
|
||||
delete range;
|
||||
bool have_init_expr = false;
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
|||
53
pform.h
53
pform.h
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef 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
|
||||
* 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,
|
||||
bool program_block, bool is_interface,
|
||||
LexicalScope::lifetime_t lifetime,
|
||||
list<named_pexpr_t>*attr);
|
||||
extern void pform_check_timeunit_prec();
|
||||
extern void pform_module_set_ports(vector<Module::port_t*>*);
|
||||
|
||||
/* This function is used to support the port definition in a
|
||||
port_definition_list. In this case, we have everything needed to
|
||||
define the port, all in one place. */
|
||||
/* These functions are used when we have a complete port definition, either
|
||||
in an ansi style or non-ansi style declaration. In this case, we have
|
||||
everything needed to define the port, all in one place. */
|
||||
extern void pform_module_define_port(const struct vlltype&li,
|
||||
perm_string name,
|
||||
NetNet::PortType,
|
||||
NetNet::Type type,
|
||||
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);
|
||||
|
||||
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,
|
||||
class_type_t*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,
|
||||
property_qualifier_t pq,
|
||||
data_type_t*data_type,
|
||||
|
|
@ -211,7 +220,8 @@ extern void pform_make_udp(perm_string name,
|
|||
* Package related functions.
|
||||
*/
|
||||
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_package_import(const struct vlltype&loc,
|
||||
PPackage*pkg, const char*ident);
|
||||
|
|
@ -246,13 +256,20 @@ extern void pform_pop_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 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,
|
||||
bool is_auto);
|
||||
LexicalScope::lifetime_t lifetime);
|
||||
|
||||
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 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<named_pexpr_t>*attr);
|
||||
|
||||
extern void pform_make_reginit(const struct vlltype&li,
|
||||
perm_string name, PExpr*expr);
|
||||
extern void pform_make_var_init(const struct vlltype&li,
|
||||
perm_string name, PExpr*expr);
|
||||
|
||||
/* Look up the names of the wires, and set the port type,
|
||||
i.e. input, output or inout. If the wire does not exist, create
|
||||
it. The second form takes a single name. */
|
||||
/* This function is used when we have an incomplete port definition in
|
||||
a non-ansi style declaration. Look up the names of the wires, and set
|
||||
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,
|
||||
list<perm_string>*names,
|
||||
list<pform_range_t>*range,
|
||||
bool signed_flag,
|
||||
list<pform_port_t>*ports,
|
||||
NetNet::PortType,
|
||||
data_type_t*dt,
|
||||
list<named_pexpr_t>*attr);
|
||||
|
||||
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
|
||||
* 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
|
||||
{
|
||||
out << size_ << "'(";
|
||||
out << *size_ << "'(";
|
||||
base_->dump(out);
|
||||
out << ")";
|
||||
}
|
||||
|
|
@ -789,6 +789,8 @@ void PBlock::dump(ostream&out, unsigned ind) const
|
|||
dump_events_(out, ind+2);
|
||||
|
||||
dump_wires_(out, ind+2);
|
||||
|
||||
dump_var_inits_(out, ind+2);
|
||||
}
|
||||
|
||||
for (unsigned idx = 0 ; idx < list_.size() ; idx += 1) {
|
||||
|
|
@ -926,7 +928,10 @@ void PDisable::dump(ostream&out, unsigned ind) const
|
|||
void PDoWhile::dump(ostream&out, unsigned ind) const
|
||||
{
|
||||
out << setw(ind) << "" << "do" << endl;
|
||||
statement_->dump(out, ind+3);
|
||||
if (statement_)
|
||||
statement_->dump(out, ind+3);
|
||||
else
|
||||
out << setw(ind+3) << "" << "/* NOOP */" << endl;
|
||||
out << setw(ind) << "" << "while (" << *cond_ << ");" << endl;
|
||||
}
|
||||
|
||||
|
|
@ -989,13 +994,19 @@ void PForeach::dump(ostream&fd, unsigned ind) const
|
|||
}
|
||||
|
||||
fd << "] /* " << get_fileline() << " */" << endl;
|
||||
statement_->dump(fd, ind+3);
|
||||
if (statement_)
|
||||
statement_->dump(fd, ind+3);
|
||||
else
|
||||
fd << setw(ind+3) << "" << "/* NOOP */" << endl;
|
||||
}
|
||||
|
||||
void PForever::dump(ostream&out, unsigned ind) const
|
||||
{
|
||||
out << setw(ind) << "" << "forever /* " << get_fileline() << " */" << endl;
|
||||
statement_->dump(out, ind+3);
|
||||
if (statement_)
|
||||
statement_->dump(out, ind+3);
|
||||
else
|
||||
out << setw(ind+3) << "" << "/* NOOP */" << endl;
|
||||
}
|
||||
|
||||
void PForStatement::dump(ostream&out, unsigned ind) const
|
||||
|
|
@ -1003,7 +1014,10 @@ void PForStatement::dump(ostream&out, unsigned ind) const
|
|||
out << setw(ind) << "" << "for (" << *name1_ << " = " << *expr1_
|
||||
<< "; " << *cond_ << "; <for_step>)" << endl;
|
||||
step_->dump(out, ind+6);
|
||||
statement_->dump(out, ind+3);
|
||||
if (statement_)
|
||||
statement_->dump(out, ind+3);
|
||||
else
|
||||
out << setw(ind+3) << "" << "/* NOOP */" << endl;
|
||||
}
|
||||
|
||||
void PFunction::dump(ostream&out, unsigned ind) const
|
||||
|
|
@ -1030,6 +1044,8 @@ void PFunction::dump(ostream&out, unsigned ind) const
|
|||
|
||||
dump_wires_(out, ind+2);
|
||||
|
||||
dump_var_inits_(out, ind+2);
|
||||
|
||||
if (statement_)
|
||||
statement_->dump(out, ind+2);
|
||||
else
|
||||
|
|
@ -1045,7 +1061,10 @@ void PRelease::dump(ostream&out, unsigned ind) const
|
|||
void PRepeat::dump(ostream&out, unsigned ind) const
|
||||
{
|
||||
out << setw(ind) << "" << "repeat (" << *expr_ << ")" << endl;
|
||||
statement_->dump(out, ind+3);
|
||||
if (statement_)
|
||||
statement_->dump(out, ind+3);
|
||||
else
|
||||
out << setw(ind+3) << "" << "/* NOOP */" << endl;
|
||||
}
|
||||
|
||||
void PReturn::dump(ostream&fd, unsigned ind) const
|
||||
|
|
@ -1072,6 +1091,8 @@ void PTask::dump(ostream&out, unsigned ind) const
|
|||
|
||||
dump_wires_(out, ind+2);
|
||||
|
||||
dump_var_inits_(out, ind+2);
|
||||
|
||||
if (statement_)
|
||||
statement_->dump(out, ind+2);
|
||||
else
|
||||
|
|
@ -1126,7 +1147,10 @@ void PTrigger::dump(ostream&out, unsigned ind) const
|
|||
void PWhile::dump(ostream&out, unsigned ind) const
|
||||
{
|
||||
out << setw(ind) << "" << "while (" << *cond_ << ")" << endl;
|
||||
statement_->dump(out, ind+3);
|
||||
if (statement_)
|
||||
statement_->dump(out, ind+3);
|
||||
else
|
||||
out << setw(ind+3) << "" << "/* NOOP */" << endl;
|
||||
}
|
||||
|
||||
void PProcess::dump(ostream&out, unsigned ind) const
|
||||
|
|
@ -1136,7 +1160,10 @@ void PProcess::dump(ostream&out, unsigned ind) const
|
|||
|
||||
dump_attributes_map(out, attributes, ind+2);
|
||||
|
||||
statement_->dump(out, ind+2);
|
||||
if (statement_)
|
||||
statement_->dump(out, ind+2);
|
||||
else
|
||||
out << setw(ind+2) << "" << "/* NOOP */" << endl;
|
||||
}
|
||||
|
||||
void AProcess::dump(ostream&out, unsigned ind) const
|
||||
|
|
@ -1157,7 +1184,10 @@ void AProcess::dump(ostream&out, unsigned ind) const
|
|||
|
||||
dump_attributes_map(out, attributes, ind+2);
|
||||
|
||||
statement_->dump(out, ind+2);
|
||||
if (statement_)
|
||||
statement_->dump(out, ind+2);
|
||||
else
|
||||
out << setw(ind+2) << "" << "/* NOOP */" << endl;
|
||||
}
|
||||
|
||||
void PSpecPath::dump(std::ostream&out, unsigned ind) const
|
||||
|
|
@ -1269,6 +1299,8 @@ void PGenerate::dump(ostream&out, unsigned indent) const
|
|||
(*idx)->dump(out, indent+2);
|
||||
}
|
||||
|
||||
dump_var_inits_(out, indent+2);
|
||||
|
||||
for (list<PProcess*>::const_iterator idx = behaviors.begin()
|
||||
; idx != behaviors.end() ; ++ idx ) {
|
||||
(*idx)->dump(out, indent+2);
|
||||
|
|
@ -1408,6 +1440,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
|
||||
{
|
||||
// Dump the task definitions.
|
||||
|
|
@ -1564,6 +1604,7 @@ void Module::dump(ostream&out) const
|
|||
(*gate)->dump(out);
|
||||
}
|
||||
|
||||
dump_var_inits_(out, 4);
|
||||
|
||||
for (list<PProcess*>::const_iterator behav = behaviors.begin()
|
||||
; 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)
|
||||
*
|
||||
* 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;
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
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
|
||||
* 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
|
||||
* 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;
|
||||
assert(pform_cur_class == 0);
|
||||
pform_cur_class = class_scope;
|
||||
|
|
@ -75,6 +79,7 @@ void pform_class_property(const struct vlltype&loc,
|
|||
if (! curp->index.empty()) {
|
||||
list<pform_range_t>*pd = new list<pform_range_t> (curp->index);
|
||||
use_type = new uarray_type_t(use_type, pd);
|
||||
FILE_NAME(use_type, loc);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
@ -138,7 +143,7 @@ void pform_end_class_declaration(const struct vlltype&loc)
|
|||
// If there were initializer statements, then collect them
|
||||
// into an implicit constructor function.
|
||||
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);
|
||||
pform_set_constructor_return(func);
|
||||
pform_set_this_class(loc, func);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef 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
|
||||
* 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;
|
||||
|
||||
/*
|
||||
* 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:
|
||||
* - The SEL_BIT is a single expression. This might me a bit select
|
||||
|
|
|
|||
|
|
@ -4,22 +4,26 @@
|
|||
# the number for a snapshot and the path to a temporary directory.
|
||||
# for example:
|
||||
#
|
||||
# sh scripts/MAKE_RELEASE.sh 0.9.1 ~/tmp
|
||||
# sh scripts/MAKE_RELEASE.sh 10.1 ~/tmp
|
||||
#
|
||||
# The above assumes that there is a tag "v0_9_1" at the point
|
||||
# The above assumes that there is a tag "v10_1" at the point
|
||||
# to be released. (The tag has the "v", but the argument to this
|
||||
# script does not have the "v"). This script extracts based on the
|
||||
# tag, uses the temporary directory to stage intermediate results,
|
||||
# and finally creates a file called verilog-0.9.1.tar.gz that
|
||||
# and finally creates a file called verilog-10.1.tar.gz that
|
||||
# contains the release ready to go.
|
||||
#
|
||||
# The complete steps to make a release x.y.z generally are:
|
||||
# The complete steps to make a release x.y generally are:
|
||||
#
|
||||
# git tag -a v0_9_1
|
||||
# Edit version_base.h to suit.
|
||||
#
|
||||
# Edit verilog.spec to suit.
|
||||
#
|
||||
# git tag -a v10_1
|
||||
# (Make the tag in the local git repository.)
|
||||
#
|
||||
# sh scripts/MAKE_RELEASE.sh 0.9.1 ~/tmp
|
||||
# (Make the snapshot bundle verilog-0.9.1.tar.gz)
|
||||
# sh scripts/MAKE_RELEASE.sh 10.1 ~/tmp
|
||||
# (Make the snapshot bundle verilog-10.1.tar.gz)
|
||||
#
|
||||
# git push --tags
|
||||
# (Publish the tag to the repository.)
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ iwidth:32
|
|||
sys_func:vpi/system.sft
|
||||
sys_func:vpi/v2005_math.sft
|
||||
sys_func:vpi/va_math.sft
|
||||
warnings:ailnpstv
|
||||
warnings:adfilnpstv
|
||||
debug:eval_tree
|
||||
debug:elaborate
|
||||
debug:emit
|
||||
|
|
|
|||
24
synth2.cc
24
synth2.cc
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2002-2015 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2002-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
|
||||
|
|
@ -103,6 +103,14 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope,
|
|||
NetNet*rsig = rval_->synthesize(des, scope, rval_);
|
||||
assert(rsig);
|
||||
|
||||
if (lval_->word() && ! dynamic_cast<NetEConst*>(lval_->word())) {
|
||||
cerr << get_fileline() << ": sorry: assignment to variable "
|
||||
"location in memory is not currently supported in "
|
||||
"synthesis." << endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
NetNet*lsig = lval_->sig();
|
||||
if (!lsig) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
|
|
@ -218,6 +226,8 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope,
|
|||
rsig = tmp;
|
||||
}
|
||||
|
||||
rsig = crop_to_width(des, rsig, lsig->vector_width());
|
||||
|
||||
if (nex_out.pin_count() > 1) {
|
||||
NexusSet tmp_set;
|
||||
nex_output(tmp_set);
|
||||
|
|
@ -555,7 +565,7 @@ bool NetCase::synth_async(Design*des, NetScope*scope,
|
|||
|
||||
// The minimum selector width is the number of inputs that
|
||||
// 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
|
||||
// guard values, and there is a default statement, then adjust
|
||||
|
|
@ -1411,6 +1421,16 @@ bool NetBlock::synth_sync(Design*des, NetScope*scope,
|
|||
are used to collect the outputs from the substatement
|
||||
for the inputs of the FF bank. */
|
||||
NetBus tmp_out (scope, tmp_set.size());
|
||||
for (unsigned idx = 0 ; idx < tmp_out.pin_count() ; idx += 1) {
|
||||
unsigned ptr = nex_map.find_nexus(tmp_set[idx]);
|
||||
ivl_assert(*this, ptr < nex_out.pin_count());
|
||||
if (nex_out.pin(ptr).is_linked()) {
|
||||
cerr << get_fileline() << ": sorry: multiple statements "
|
||||
"assigning to the same flip-flop are not yet "
|
||||
"supported in synthesis." << endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Create a temporary ff_ce (FF clock-enable) that
|
||||
accounts for the subset of outputs that this
|
||||
|
|
|
|||
|
|
@ -171,13 +171,6 @@ extern "C" unsigned ivl_expr_lineno(ivl_expr_t net)
|
|||
return net->lineno;
|
||||
}
|
||||
|
||||
inline static const char *basename(ivl_scope_t scope, const char *inst)
|
||||
{
|
||||
inst += strlen(ivl_scope_name(scope));
|
||||
assert(*inst == '.');
|
||||
return inst+1;
|
||||
}
|
||||
|
||||
extern "C" ivl_variable_type_t ivl_const_type(ivl_net_const_t net)
|
||||
{
|
||||
assert(net);
|
||||
|
|
|
|||
7
t-dll.cc
7
t-dll.cc
|
|
@ -151,13 +151,6 @@ void ivl_net_const_s::operator delete(void*, size_t)
|
|||
|
||||
static StringHeapLex net_const_strings;
|
||||
|
||||
inline static const char *basename(ivl_scope_t scope, const char *inst)
|
||||
{
|
||||
inst += strlen(ivl_scope_name(scope));
|
||||
assert(*inst == '.');
|
||||
return inst+1;
|
||||
}
|
||||
|
||||
static perm_string make_scope_name(const hname_t&name)
|
||||
{
|
||||
if (! name.has_numbers())
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ using namespace std;
|
|||
|
||||
static const char*version_string =
|
||||
"Icarus Verilog BLIF Code Generator " VERSION " (" VERSION_TAG ")\n\n"
|
||||
"Copyright (c) 2013 Stephen Williams (steve@icarus.com)\n\n"
|
||||
"Copyright (c) 2013,2015 Stephen Williams (steve@icarus.com)\n\n"
|
||||
" This program is free software; you can redistribute it and/or modify\n"
|
||||
" it under the terms of the GNU General Public License as published by\n"
|
||||
" the Free Software Foundation; either version 2 of the License, or\n"
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2015 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
|
||||
|
|
@ -30,7 +30,7 @@
|
|||
|
||||
static const char*version_string =
|
||||
"Icarus Verilog NULL Code Generator " VERSION " (" VERSION_TAG ")\n\n"
|
||||
"Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com)\n\n"
|
||||
"Copyright (c) 2000-2015 Stephen Williams (steve@icarus.com)\n\n"
|
||||
" This program is free software; you can redistribute it and/or modify\n"
|
||||
" it under the terms of the GNU General Public License as published by\n"
|
||||
" the Free Software Foundation; either version 2 of the License, or\n"
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2014,2015 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
|
||||
|
|
@ -34,7 +34,7 @@ using namespace std;
|
|||
|
||||
static const char*version_string =
|
||||
"Icarus Verilog SIZER Statistics Generator " VERSION " (" VERSION_TAG ")\n\n"
|
||||
"Copyright (c) 2014 Stephen Williams (steve@icarus.com)\n\n"
|
||||
"Copyright (c) 2014,2015 Stephen Williams (steve@icarus.com)\n\n"
|
||||
" This program is free software; you can redistribute it and/or modify\n"
|
||||
" it under the terms of the GNU General Public License as published by\n"
|
||||
" the Free Software Foundation; either version 2 of the License, or\n"
|
||||
|
|
|
|||
|
|
@ -42,7 +42,6 @@ void show_constant(ivl_net_const_t net)
|
|||
case IVL_VT_REAL:
|
||||
fprintf(out, "%f", ivl_const_real(net));
|
||||
break;
|
||||
break;
|
||||
default:
|
||||
fprintf(out, "<unsupported type>");
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
// are not used here.
|
||||
|
||||
// target_design()
|
||||
unusedFunction:stub.c:1773
|
||||
unusedFunction:stub.c:1774
|
||||
|
||||
// target_query()
|
||||
unusedFunction:stub.c:1843
|
||||
unusedFunction:stub.c:1844
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@
|
|||
|
||||
static const char*version_string =
|
||||
"Icarus Verilog STUB Code Generator " VERSION " (" VERSION_TAG ")\n\n"
|
||||
"Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com)\n\n"
|
||||
"Copyright (c) 2000-2015 Stephen Williams (steve@icarus.com)\n\n"
|
||||
" This program is free software; you can redistribute it and/or modify\n"
|
||||
" it under the terms of the GNU General Public License as published by\n"
|
||||
" the Free Software Foundation; either version 2 of the License, or\n"
|
||||
|
|
|
|||
|
|
@ -1180,7 +1180,7 @@ static long get_number_as_long(ivl_expr_t expr)
|
|||
}
|
||||
|
||||
if (ivl_expr_signed(expr) && bits[nbits-1] == '1' &&
|
||||
nbits < 8*sizeof(long)) imm |= -1L << nbits;
|
||||
nbits < 8*sizeof(long)) imm |= -1UL << nbits;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
functor:cprop
|
||||
functor:nodangle
|
||||
flag:DLL=vhdl.tgt
|
||||
flag:DISABLE_CONCATZ_GENERATION=true
|
||||
|
|
|
|||
|
|
@ -1407,7 +1407,7 @@ static void emit_lpm_ff(ivl_scope_t scope, ivl_lpm_t lpm)
|
|||
}
|
||||
nex = ivl_lpm_sync_set(lpm);
|
||||
if (nex) {
|
||||
if (! sset_bits || (sset_bits && (sset_bits[0] == '1'))) {
|
||||
if (! sset_bits || (sset_bits[0] == '1')) {
|
||||
emit_nexus_as_ca(scope, nex, 0, 0);
|
||||
if (have_data) fprintf(vlog_out, " | ");
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
* 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
|
||||
* 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
|
||||
* 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)
|
||||
{
|
||||
|
|
@ -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_CLASS)) {
|
||||
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);
|
||||
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. */
|
||||
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;
|
||||
call_mod_scope = 0;
|
||||
} else {
|
||||
|
|
@ -938,3 +947,30 @@ void get_sig_msb_lsb(ivl_signal_t sig, int *msb, int *lsb)
|
|||
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
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -24,33 +24,6 @@
|
|||
|
||||
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)
|
||||
{
|
||||
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
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -30,7 +30,7 @@
|
|||
|
||||
static const char*version_string =
|
||||
"Icarus Verilog VLOG95 Code Generator " VERSION " (" VERSION_TAG ")\n\n"
|
||||
"Copyright (C) 2010-2013 Cary R. (cygcary@yahoo.com)\n\n"
|
||||
"Copyright (C) 2010-2015 Cary R. (cygcary@yahoo.com)\n\n"
|
||||
" This program is free software; you can redistribute it and/or modify\n"
|
||||
" it under the terms of the GNU General Public License as published by\n"
|
||||
" the Free Software Foundation; either version 2 of the License, or\n"
|
||||
|
|
@ -60,7 +60,6 @@ int target_design(ivl_design_t des)
|
|||
{
|
||||
ivl_scope_t *roots;
|
||||
unsigned nroots, idx;
|
||||
unsigned has_root_scope = 0;
|
||||
const char*path = ivl_design_flag(des, "-o");
|
||||
/* Set the indent spacing with the -pspacing flag passed to iverilog
|
||||
* (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])) {
|
||||
case IVL_SCT_FUNCTION:
|
||||
case IVL_SCT_TASK:
|
||||
if (! has_root_scope) {
|
||||
fprintf(vlog_out, "module ivl_root_scope;\n");
|
||||
indent += indent_incr;
|
||||
has_root_scope = 1;
|
||||
}
|
||||
/* Create a separate module for each task/function.
|
||||
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;
|
||||
|
||||
/* Say this task/function has a parent so the
|
||||
* definition is emitted correctly. */
|
||||
emit_scope(roots[idx], roots[idx]);
|
||||
|
||||
indent -= indent_incr;
|
||||
assert(indent == 0);
|
||||
fprintf(vlog_out, "endmodule /* ivl_root_scope_%p */\n",
|
||||
roots[idx]);
|
||||
break;
|
||||
default:
|
||||
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. */
|
||||
for (idx = 0; idx < nroots; idx += 1) emit_scope(roots[idx], 0);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef 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
|
||||
* 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);
|
||||
|
||||
/*
|
||||
* Convert a timescale value to a string.
|
||||
*/
|
||||
extern const char*get_time_const(int time_value);
|
||||
|
||||
/*
|
||||
* Cleanup functions.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -47,8 +47,8 @@ CPPFLAGS = $(INCLUDE_PATH) @CPPFLAGS@ @DEFS@ @PICFLAG@
|
|||
CFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CC@ @CFLAGS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
|
||||
O = vvp.o draw_class.o draw_enum.o draw_mux.o draw_substitute.o draw_net_input.o \
|
||||
draw_switch.o draw_ufunc.o draw_vpi.o \
|
||||
O = vvp.o draw_class.o draw_delay.o draw_enum.o draw_mux.o draw_net_input.o \
|
||||
draw_substitute.o draw_switch.o draw_ufunc.o draw_vpi.o \
|
||||
eval_bool.o \
|
||||
eval_condit.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
|
||||
* 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)
|
||||
dly_width = 0;
|
||||
|
||||
draw_delay(net, dly_width, 0, d_rise, d_fall, d_decay);
|
||||
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));
|
||||
|
|
|
|||
|
|
@ -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
|
||||
* 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);
|
||||
if (cptr) {
|
||||
char tmp[64];
|
||||
char *result = 0;
|
||||
ivl_expr_t d_rise, d_fall, d_decay;
|
||||
unsigned dly_width = 0;
|
||||
char *dly;
|
||||
|
||||
/* Constants should have exactly 1 pin, with a literal value. */
|
||||
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_decay = ivl_const_delay(cptr, 2);
|
||||
|
||||
/* We have a delayed constant, so we need to build some code. */
|
||||
dly = "";
|
||||
if (d_rise != 0) {
|
||||
char tmp[128];
|
||||
fprintf(vvp_out, "L_%p/d .functor BUFT 1, %s, "
|
||||
"C4<0>, C4<0>, C4<0>;\n", cptr, result);
|
||||
free(result);
|
||||
|
||||
/* Is this a fixed or variable delay? */
|
||||
if (number_is_immediate(d_rise, 64, 0) &&
|
||||
number_is_immediate(d_fall, 64, 0) &&
|
||||
number_is_immediate(d_decay, 64, 0)) {
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
snprintf(tmp, sizeof tmp, "L_%p", cptr);
|
||||
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);
|
||||
|
||||
snprintf(tmp, sizeof tmp, "L_%p", cptr);
|
||||
result = strdup(tmp);
|
||||
draw_delay(cptr, dly_width, 0, d_rise, d_fall, d_decay);
|
||||
dly = "/d";
|
||||
}
|
||||
fprintf(vvp_out, "L_%p%s .functor BUFT 1, %s, C4<0>, C4<0>, C4<0>;\n",
|
||||
cptr, dly, result);
|
||||
free(result);
|
||||
|
||||
return result;
|
||||
snprintf(tmp, sizeof tmp, "L_%p", cptr);
|
||||
return strdup(tmp);
|
||||
}
|
||||
|
||||
lpm = ivl_nexus_ptr_lpm(nptr);
|
||||
|
|
@ -711,6 +662,8 @@ static void draw_net_input_x(ivl_nexus_t nex,
|
|||
tmp += strlen(tmp);
|
||||
switch (res) {
|
||||
case IVL_SIT_TRI:
|
||||
case IVL_SIT_TRIAND:
|
||||
case IVL_SIT_TRIOR:
|
||||
case IVL_SIT_UWIRE:
|
||||
for (jdx = 0 ; jdx < wid ; jdx += 1)
|
||||
*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
|
||||
* 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 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);
|
||||
if (ivl_island_flag_test(island, 0) == 0)
|
||||
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*)];
|
||||
|
||||
if (enable && rise_exp) {
|
||||
assert(fall_exp && decay_exp);
|
||||
|
||||
/* If the enable has a delay, then generate a .delay
|
||||
node to delay the input by the specified amount. Do
|
||||
the delay outside of the island so that the island
|
||||
processing doesn't have to deal with it. */
|
||||
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);
|
||||
str_e = str_e_buf;
|
||||
|
||||
fprintf(vvp_out, "%s/d .delay 1 "
|
||||
"(%" 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);
|
||||
fprintf(vvp_out, "%s .import I%p, L_%p;\n", str_e, island, sw);
|
||||
|
||||
} else if (enable) {
|
||||
str_e = draw_island_net_input(island, enable);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2014-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
|
||||
|
|
@ -76,8 +76,8 @@ static int draw_condition_binary_compare(ivl_expr_t expr)
|
|||
%cmp instruction. */
|
||||
if (ivl_expr_width(le)==use_wid && test_immediate_vec4_ok(le)) {
|
||||
ivl_expr_t tmp = le;
|
||||
re = le;
|
||||
le = tmp;
|
||||
le = re;
|
||||
re = tmp;
|
||||
}
|
||||
|
||||
draw_eval_vec4(le);
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@ long get_number_immediate(ivl_expr_t expr)
|
|||
assert(0);
|
||||
}
|
||||
if (ivl_expr_signed(expr) && bits[nbits-1]=='1' &&
|
||||
nbits < 8*sizeof(long)) imm |= -1L << nbits;
|
||||
nbits < 8*sizeof(long)) imm |= -1UL << nbits;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1032,7 +1032,7 @@ static void draw_string_vec4(ivl_expr_t expr)
|
|||
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 8) {
|
||||
tmp <<= 8;
|
||||
tmp |= *p;
|
||||
tmp |= (unsigned long)*p;
|
||||
p += 1;
|
||||
tmp_wid += 8;
|
||||
if (tmp_wid == 32) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
* 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);
|
||||
|
||||
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;
|
||||
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))
|
||||
bit_limit = ivl_lval_width(lval);
|
||||
|
||||
get_vec_from_lval_slice(lval, slices+lidx, bit_limit);
|
||||
if (lidx > 0) {
|
||||
get_vec_from_lval_slice(lval, slices+lidx-1, bit_limit);
|
||||
if (cur_bit > 0) {
|
||||
fprintf(vvp_out, " %%concat/vec4;\n");
|
||||
}
|
||||
|
||||
|
|
@ -555,28 +555,130 @@ static int show_stmt_assign_vector(ivl_statement_t net)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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)
|
||||
enum real_lval_type_e {
|
||||
REAL_NO_TYPE = 0,
|
||||
REAL_SIMPLE_WORD,
|
||||
REAL_MEMORY_WORD_STATIC,
|
||||
REAL_MEMORY_WORD_DYNAMIC
|
||||
};
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
assert(var != 0);
|
||||
|
||||
if (ivl_signal_dimensions(var) == 0) {
|
||||
fprintf(vvp_out, " %%store/real v%p_0;\n", var);
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@
|
|||
|
||||
static const char*version_string =
|
||||
"Icarus Verilog VVP Code Generator " VERSION " (" VERSION_TAG ")\n\n"
|
||||
"Copyright (c) 2001-2011 Stephen Williams (steve@icarus.com)\n\n"
|
||||
"Copyright (c) 2001-2015 Stephen Williams (steve@icarus.com)\n\n"
|
||||
" This program is free software; you can redistribute it and/or modify\n"
|
||||
" it under the terms of the GNU General Public License as published by\n"
|
||||
" the Free Software Foundation; either version 2 of the License, or\n"
|
||||
|
|
|
|||
|
|
@ -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 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.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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
|
||||
* 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;
|
||||
|
||||
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
|
||||
// to an array word. In that case, run off somewhere else to
|
||||
// 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_statement_t stmt = ivl_process_stmt(net);
|
||||
|
||||
int init_flag = 0;
|
||||
int push_flag = 0;
|
||||
|
||||
(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);
|
||||
|
||||
if (strcmp(attr->key, "_ivl_schedule_init") == 0) {
|
||||
|
||||
init_flag = 1;
|
||||
|
||||
}
|
||||
|
||||
if (strcmp(attr->key, "_ivl_schedule_push") == 0) {
|
||||
|
||||
push_flag = 1;
|
||||
|
|
@ -2349,7 +2365,9 @@ int draw_process(ivl_process_t net, void*x)
|
|||
|
||||
case IVL_PR_INITIAL:
|
||||
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);
|
||||
} else {
|
||||
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
|
||||
* 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 );
|
||||
}
|
||||
|
||||
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,
|
||||
datatype_flag, sig, iword, msb, lsb,
|
||||
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.
|
||||
*/
|
||||
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 fall_exp = ivl_logic_delay(lptr, 1);
|
||||
|
|
@ -730,49 +730,7 @@ static void draw_delay(ivl_net_logic_t lptr)
|
|||
delay_wid = 0;
|
||||
}
|
||||
|
||||
/* 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 ") 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");
|
||||
}
|
||||
}
|
||||
draw_delay(lptr, delay_wid, 0, rise_exp, fall_exp, decay_exp);
|
||||
}
|
||||
|
||||
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");
|
||||
|
||||
/* 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)
|
||||
|
|
@ -1112,7 +1070,7 @@ static void draw_logic_in_scope(ivl_net_logic_t lptr)
|
|||
free(input_strings);
|
||||
|
||||
/* 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)
|
||||
|
|
@ -1312,20 +1270,8 @@ static const char* draw_lpm_output_delay(ivl_lpm_t net, ivl_variable_type_t dt)
|
|||
|
||||
const char*dly = "";
|
||||
if (d_rise != 0) {
|
||||
assert(number_is_immediate(d_rise, 64, 0));
|
||||
assert(number_is_immediate(d_fall, 64, 0));
|
||||
assert(number_is_immediate(d_decay, 64, 0));
|
||||
|
||||
assert(! number_is_unknown(d_rise));
|
||||
assert(! number_is_unknown(d_fall));
|
||||
assert(! number_is_unknown(d_decay));
|
||||
|
||||
draw_delay(net, width, 0, d_rise, d_fall, d_decay);
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#norootforbuild
|
||||
#
|
||||
%define rev_date 20150603
|
||||
%define rev_date 20170824
|
||||
# Normally, the suff-ix is %nil, meaning the suffix is to not be used.
|
||||
# But if the builder wants to make a suffixed package, he may set this
|
||||
# to a value (i.e. -test) to cause suffixes to be put in all the right
|
||||
|
|
@ -10,11 +10,11 @@
|
|||
#
|
||||
Summary: Icarus Verilog
|
||||
Name: verilog%{suff}
|
||||
Version: 0.10.0.%{rev_date}
|
||||
Version: 10.2
|
||||
Release: 0
|
||||
License: GPL
|
||||
Group: Productivity/Scientific/Electronics
|
||||
Source: verilog%{suff}-%{rev_date}.tar.gz
|
||||
Source: verilog%{suff}-%{version}.tar.gz
|
||||
URL: http://www.icarus.com/eda/verilog/index.html
|
||||
Packager: Stephen Williams <steve@icarus.com>
|
||||
|
||||
|
|
@ -32,7 +32,7 @@ engineering formats, including simulation. It strives to be true
|
|||
to the IEEE-1364 standard.
|
||||
|
||||
%prep
|
||||
%setup -n verilog%{suff}-%{rev_date}
|
||||
%setup -n verilog-%{version}
|
||||
|
||||
%build
|
||||
if test X%{suff} != X
|
||||
|
|
|
|||
|
|
@ -29,10 +29,7 @@ static void run_string(const char*txt)
|
|||
if (cp[0] == '%' && cp[1] != 0) {
|
||||
switch (cp[1]) {
|
||||
case 'M':
|
||||
fprintf(stdout, "%u", VERSION_MAJOR1);
|
||||
break;
|
||||
case 'm':
|
||||
fprintf(stdout, "%u", VERSION_MAJOR2);
|
||||
fprintf(stdout, "%u", VERSION_MAJOR);
|
||||
break;
|
||||
case 'n':
|
||||
fprintf(stdout, "%u", VERSION_MINOR);
|
||||
|
|
|
|||
|
|
@ -3,17 +3,17 @@
|
|||
* Edit this definition in version_base.in to define the base version
|
||||
* number for the compiled result.
|
||||
*/
|
||||
# define VERSION_MAJOR1 0
|
||||
# define VERSION_MAJOR2 10
|
||||
# define VERSION_MINOR 0
|
||||
# define VERSION_EXTRA "(devel)"
|
||||
# define VERSION_MAJOR 10
|
||||
# define VERSION_MINOR 2
|
||||
|
||||
/* This is a concatenation of MAJOR1.MAJOR2 that is used by
|
||||
vams_simparam.c to make a double value. */
|
||||
# define VERSION_MAJOR 0.10
|
||||
/*
|
||||
* This will be appended to the version. Use this to mark development
|
||||
* versions and the like.
|
||||
*/
|
||||
# define VERSION_EXTRA " (stable)"
|
||||
|
||||
# define VERSION_STRINGIFY(x) #x
|
||||
# define VERSION_STR(a,b,extra) VERSION_STRINGIFY(a.b) " " extra
|
||||
# define VERSION_STR(a,b,extra) VERSION_STRINGIFY(a.b) extra
|
||||
|
||||
#define VERSION VERSION_STR(VERSION_MAJOR,VERSION_MINOR,VERSION_EXTRA)
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -61,7 +61,9 @@ ExpAttribute::ExpAttribute(ExpName*bas, perm_string nam)
|
|||
|
||||
ExpAttribute::~ExpAttribute()
|
||||
{
|
||||
delete base_;
|
||||
/* Different attributes can point to the same base so we cannot delete this here.
|
||||
* Look at the vhdl_range test with valgrind to see this issue. */
|
||||
// delete base_;
|
||||
}
|
||||
|
||||
Expression*ExpAttribute::clone() const
|
||||
|
|
|
|||
|
|
@ -874,7 +874,7 @@ const VType* ExpName::probe_prefix_type_(Entity*ent, ScopeBase*scope) const
|
|||
}
|
||||
|
||||
/*
|
||||
* This method is the probe_type() imlementation for ExpName objects
|
||||
* This method is the probe_type() implementation for ExpName objects
|
||||
* that have prefix parts. In this case we try to get the type of the
|
||||
* prefix and interpret the name in that context.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ const char COPYRIGHT[] =
|
|||
* information to the file named <path>.
|
||||
*
|
||||
* elaboration=<path>
|
||||
* Enable debugging of elaboratin by dumping elaboration
|
||||
* Enable debugging of elaboration by dumping elaboration
|
||||
* process information to the file named <path>.
|
||||
*
|
||||
* entities=<path>
|
||||
|
|
|
|||
|
|
@ -665,7 +665,7 @@ component_configuration
|
|||
block_configuration_opt
|
||||
K_end K_for ';'
|
||||
{
|
||||
sorrymsg(@1, "Component configuration in not yet supported");
|
||||
sorrymsg(@1, "Component configuration in not yet supported\n");
|
||||
if($3) delete $3;
|
||||
delete $2;
|
||||
}
|
||||
|
|
@ -834,14 +834,14 @@ else_when_waveform
|
|||
concurrent_signal_assignment_statement /* IEEE 1076-2008 P11.6 */
|
||||
: concurrent_simple_signal_assignment
|
||||
|
||||
| IDENTIFIER ':' concurrent_simple_signal_assignment
|
||||
| IDENTIFIER ':' concurrent_simple_signal_assignment
|
||||
{ delete[] $1;
|
||||
$$ = $3;
|
||||
}
|
||||
|
||||
| concurrent_conditional_signal_assignment
|
||||
|
||||
| IDENTIFIER ':' concurrent_conditional_signal_assignment
|
||||
| IDENTIFIER ':' concurrent_conditional_signal_assignment
|
||||
{ delete[] $1;
|
||||
$$ = $3;
|
||||
}
|
||||
|
|
@ -878,7 +878,7 @@ configuration_declaration
|
|||
K_end K_configuration_opt identifier_opt ';'
|
||||
{
|
||||
if(design_entities.find(lex_strings.make($4)) == design_entities.end())
|
||||
errormsg(@4, "Couldn't find entity %s used in configuration declaration", $4);
|
||||
errormsg(@4, "Couldn't find entity %s used in configuration declaration\n", $4);
|
||||
//choose_architecture_for_entity();
|
||||
sorrymsg(@1, "Configuration declaration is not yet supported.\n");
|
||||
}
|
||||
|
|
@ -1873,10 +1873,10 @@ primary
|
|||
else if(!strcasecmp($2, "fs"))
|
||||
unit = ExpTime::FS;
|
||||
else
|
||||
errormsg(@2, "Invalid time unit (accepted are fs, ps, ns, us, ms, s).");
|
||||
errormsg(@2, "Invalid time unit (accepted are fs, ps, ns, us, ms, s).\n");
|
||||
|
||||
if($1 < 0)
|
||||
errormsg(@1, "Time cannot be negative.");
|
||||
errormsg(@1, "Time cannot be negative.\n");
|
||||
|
||||
ExpTime*tmp = new ExpTime($1, unit);
|
||||
FILE_NAME(tmp, @1);
|
||||
|
|
@ -2586,7 +2586,7 @@ suffix
|
|||
{ $$ = $1; }
|
||||
| K_all
|
||||
{ //do not have now better idea than using char constant
|
||||
$$ = strcpy(new char[strlen("all"+1)], "all");
|
||||
$$ = strdup("all");
|
||||
}
|
||||
;
|
||||
|
||||
|
|
|
|||
|
|
@ -169,7 +169,7 @@ class ActiveScope : public ScopeBase {
|
|||
bool is_vector_name(perm_string name) const;
|
||||
|
||||
// Locate the subprogram by name. The subprogram body uses
|
||||
// this to locate the sobprogram declaration. Note that the
|
||||
// this to locate the subprogram declaration. Note that the
|
||||
// subprogram may be in a package header.
|
||||
SubprogramHeader* recall_subprogram(perm_string name) const;
|
||||
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ O = sys_table.o sys_convert.o sys_countdrivers.o sys_darray.o sys_deposit.o sys_
|
|||
sys_random.o sys_random_mti.o sys_readmem.o sys_readmem_lex.o sys_scanf.o \
|
||||
sys_sdf.o sys_time.o sys_vcd.o sys_vcdoff.o vcd_priv.o mt19937int.o \
|
||||
sys_priv.o sdf_parse.o sdf_lexor.o stringheap.o vams_simparam.o \
|
||||
table_mod.o table_mod_lexor.o table_mod_parse.o
|
||||
table_mod.o table_mod_parse.o table_mod_lexor.o
|
||||
OPP = vcd_priv2.o
|
||||
|
||||
ifeq (@HAVE_LIBZ@,yes)
|
||||
|
|
|
|||
218
vpi/cppcheck.sup
218
vpi/cppcheck.sup
|
|
@ -3,143 +3,143 @@
|
|||
// problems will not be fixed.
|
||||
|
||||
// fstapi.c from GTKWave
|
||||
obsoleteFunctionsasctime:fstapi.c:929
|
||||
obsoleteFunctionsalloca:fstapi.c:2304
|
||||
unreadVariable:fstapi.c:1647
|
||||
variableScope:fstapi.c:665
|
||||
variableScope:fstapi.c:1337
|
||||
obsoleteFunctionsasctime:fstapi.c:930
|
||||
obsoleteFunctionsalloca:fstapi.c:2305
|
||||
unreadVariable:fstapi.c:1648
|
||||
variableScope:fstapi.c:666
|
||||
variableScope:fstapi.c:1338
|
||||
variableScope:fstapi.c:1395
|
||||
variableScope:fstapi.c:1978
|
||||
variableScope:fstapi.c:2107
|
||||
variableScope:fstapi.c:2540
|
||||
variableScope:fstapi.c:1339
|
||||
variableScope:fstapi.c:1396
|
||||
variableScope:fstapi.c:1979
|
||||
variableScope:fstapi.c:2108
|
||||
variableScope:fstapi.c:2541
|
||||
variableScope:fstapi.c:2732
|
||||
variableScope:fstapi.c:2542
|
||||
variableScope:fstapi.c:2733
|
||||
variableScope:fstapi.c:2737
|
||||
variableScope:fstapi.c:2853
|
||||
variableScope:fstapi.c:2892
|
||||
variableScope:fstapi.c:2734
|
||||
variableScope:fstapi.c:2738
|
||||
variableScope:fstapi.c:2854
|
||||
variableScope:fstapi.c:2893
|
||||
variableScope:fstapi.c:3611
|
||||
variableScope:fstapi.c:3785
|
||||
variableScope:fstapi.c:3787
|
||||
variableScope:fstapi.c:4229
|
||||
variableScope:fstapi.c:2894
|
||||
variableScope:fstapi.c:3612
|
||||
variableScope:fstapi.c:3786
|
||||
variableScope:fstapi.c:3788
|
||||
variableScope:fstapi.c:4230
|
||||
variableScope:fstapi.c:4239
|
||||
variableScope:fstapi.c:4502
|
||||
variableScope:fstapi.c:4773
|
||||
variableScope:fstapi.c:4776
|
||||
variableScope:fstapi.c:5270
|
||||
variableScope:fstapi.c:5274
|
||||
variableScope:fstapi.c:4231
|
||||
variableScope:fstapi.c:4240
|
||||
variableScope:fstapi.c:4503
|
||||
variableScope:fstapi.c:4774
|
||||
variableScope:fstapi.c:4777
|
||||
variableScope:fstapi.c:5271
|
||||
variableScope:fstapi.c:5275
|
||||
variableScope:fstapi.c:5431
|
||||
variableScope:fstapi.c:5489
|
||||
variableScope:fstapi.c:5802
|
||||
variableScope:fstapi.c:5805
|
||||
variableScope:fstapi.c:6041
|
||||
variableScope:fstapi.c:6146
|
||||
variableScope:fstapi.c:5276
|
||||
variableScope:fstapi.c:5432
|
||||
variableScope:fstapi.c:5490
|
||||
variableScope:fstapi.c:5803
|
||||
variableScope:fstapi.c:5806
|
||||
variableScope:fstapi.c:6042
|
||||
variableScope:fstapi.c:6147
|
||||
variableScope:fstapi.c:6178
|
||||
variableScope:fstapi.c:6406
|
||||
variableScope:fstapi.c:6148
|
||||
variableScope:fstapi.c:6179
|
||||
variableScope:fstapi.c:6407
|
||||
// These functions are not used by Icarus
|
||||
// fstReaderClrFacProcessMask()
|
||||
unusedFunction:fstapi.c:3343
|
||||
unusedFunction:fstapi.c:3344
|
||||
// fstReaderClrFacProcessMaskAll()
|
||||
unusedFunction:fstapi.c:3372
|
||||
unusedFunction:fstapi.c:3373
|
||||
// fstReaderGetAliasCount()
|
||||
unusedFunction:fstapi.c:3435
|
||||
unusedFunction:fstapi.c:3436
|
||||
// fstReaderGetCurrentFlatScope()
|
||||
unusedFunction:fstapi.c:3181
|
||||
unusedFunction:fstapi.c:3182
|
||||
// fstReaderGetAliasCount()
|
||||
unusedFunction:fstapi.c:3278
|
||||
unusedFunction:fstapi.c:3279
|
||||
// fstReaderGetCurrentScopeUserInfo()
|
||||
unusedFunction:fstapi.c:3195
|
||||
unusedFunction:fstapi.c:3196
|
||||
// fstReaderGetDateString()
|
||||
unusedFunction:fstapi.c:3463
|
||||
unusedFunction:fstapi.c:3464
|
||||
// fstReaderGetDoubleEndianMatchState()
|
||||
unusedFunction:fstapi.c:3449
|
||||
unusedFunction:fstapi.c:3450
|
||||
// fstReaderGetDumpActivityChangeTime()
|
||||
unusedFunction:fstapi.c:3491
|
||||
unusedFunction:fstapi.c:3492
|
||||
// fstReaderGetDumpActivityChangeValue()
|
||||
unusedFunction:fstapi.c:3506
|
||||
unusedFunction:fstapi.c:3507
|
||||
// fstReaderGetEndTime()
|
||||
unusedFunction:fstapi.c:3400
|
||||
unusedFunction:fstapi.c:3401
|
||||
// fstReaderGetFacProcessMask()
|
||||
unusedFunction:fstapi.c:3306
|
||||
unusedFunction:fstapi.c:3307
|
||||
// fstReaderGetFileType()
|
||||
unusedFunction:fstapi.c:3470
|
||||
unusedFunction:fstapi.c:3471
|
||||
// fstReaderGetFseekFailed()
|
||||
unusedFunction:fstapi.c:3291
|
||||
unusedFunction:fstapi.c:3292
|
||||
// fstReaderGetMaxHandle()
|
||||
unusedFunction:fstapi.c:3428
|
||||
unusedFunction:fstapi.c:3429
|
||||
// fstReaderGetMemoryUsedByWriter()
|
||||
unusedFunction:fstapi.c:3407
|
||||
unusedFunction:fstapi.c:3408
|
||||
// fstReaderGetNumberDumpActivityChanges()
|
||||
unusedFunction:fstapi.c:3484
|
||||
unusedFunction:fstapi.c:3485
|
||||
// fstReaderGetScopeCount()
|
||||
unusedFunction:fstapi.c:3414
|
||||
unusedFunction:fstapi.c:3415
|
||||
// fstReaderGetStartTime()
|
||||
unusedFunction:fstapi.c:3393
|
||||
unusedFunction:fstapi.c:3394
|
||||
// fstReaderGetTimescale()
|
||||
unusedFunction:fstapi.c:3386
|
||||
unusedFunction:fstapi.c:3387
|
||||
// fstReaderGetTimezero()
|
||||
unusedFunction:fstapi.c:3477
|
||||
unusedFunction:fstapi.c:3478
|
||||
// fstReaderGetValueChangeSectionCount()
|
||||
unusedFunction:fstapi.c:3442
|
||||
unusedFunction:fstapi.c:3443
|
||||
// fstReaderGetValueFromHandleAtTime()
|
||||
unusedFunction:fstapi.c:5684
|
||||
unusedFunction:fstapi.c:5685
|
||||
// fstReaderGetVarCount()
|
||||
unusedFunction:fstapi.c:3421
|
||||
unusedFunction:fstapi.c:3422
|
||||
// fstReaderGetVersionString()
|
||||
unusedFunction:fstapi.c:3456
|
||||
unusedFunction:fstapi.c:3457
|
||||
// fstReaderIterBlocks()
|
||||
unusedFunction:fstapi.c:4651
|
||||
unusedFunction:fstapi.c:4652
|
||||
// fstReaderIterBlocksSetNativeDoublesOnCallback()
|
||||
unusedFunction:fstapi.c:3556
|
||||
unusedFunction:fstapi.c:3557
|
||||
// fstReaderIterateHier()
|
||||
unusedFunction:fstapi.c:3781
|
||||
unusedFunction:fstapi.c:3782
|
||||
// fstReaderIterateHierRewind()
|
||||
unusedFunction:fstapi.c:3761
|
||||
unusedFunction:fstapi.c:3762
|
||||
// fstReaderOpen()
|
||||
unusedFunction:fstapi.c:4549
|
||||
unusedFunction:fstapi.c:4550
|
||||
// fstReaderOpenForUtilitiesOnly()
|
||||
unusedFunction:fstapi.c:4541
|
||||
unusedFunction:fstapi.c:4542
|
||||
// fstReaderPushScope()
|
||||
unusedFunction:fstapi.c:3243
|
||||
unusedFunction:fstapi.c:3244
|
||||
// fstReaderResetScope()
|
||||
unusedFunction:fstapi.c:3232
|
||||
unusedFunction:fstapi.c:3233
|
||||
// fstReaderSetFacProcessMask()
|
||||
unusedFunction:fstapi.c:3325
|
||||
unusedFunction:fstapi.c:3326
|
||||
// fstReaderSetFacProcessMaskAll()
|
||||
unusedFunction:fstapi.c:3361
|
||||
unusedFunction:fstapi.c:3362
|
||||
// fstReaderSetLimitTimeRange()
|
||||
unusedFunction:fstapi.c:3521
|
||||
unusedFunction:fstapi.c:3522
|
||||
// fstReaderSetUnlimitedTimeRange()
|
||||
unusedFunction:fstapi.c:3534
|
||||
unusedFunction:fstapi.c:3535
|
||||
// fstReaderSetVcdExtensions()
|
||||
unusedFunction:fstapi.c:3545
|
||||
unusedFunction:fstapi.c:3546
|
||||
// fstUtilityEscToBin()
|
||||
unusedFunction:fstapi.c:6484
|
||||
unusedFunction:fstapi.c:6485
|
||||
// fstWriterCreateVar2()
|
||||
unusedFunction:fstapi.c:2527
|
||||
unusedFunction:fstapi.c:2528
|
||||
// fstWriterEmitVariableLengthValueChange()
|
||||
unusedFunction:fstapi.c:2846
|
||||
unusedFunction:fstapi.c:2847
|
||||
// fstWriterGetFseekFailed()
|
||||
unusedFunction:fstapi.c:2510
|
||||
unusedFunction:fstapi.c:2511
|
||||
// fstWriterSetAttrEnd()
|
||||
unusedFunction:fstapi.c:2713
|
||||
unusedFunction:fstapi.c:2714
|
||||
// fstWriterSetComment()
|
||||
unusedFunction:fstapi.c:2359
|
||||
unusedFunction:fstapi.c:2360
|
||||
// fstWriterSetEnvVar()
|
||||
unusedFunction:fstapi.c:2371
|
||||
unusedFunction:fstapi.c:2372
|
||||
// fstWriterSetFileType()
|
||||
unusedFunction:fstapi.c:2234
|
||||
unusedFunction:fstapi.c:2235
|
||||
// fstWriterSetParallelMode()
|
||||
unusedFunction:fstapi.c:2470
|
||||
unusedFunction:fstapi.c:2471
|
||||
// fstWriterSetTimezero()
|
||||
unusedFunction:fstapi.c:2435
|
||||
unusedFunction:fstapi.c:2436
|
||||
// fstWriterSetValueList()
|
||||
unusedFunction:fstapi.c:2365
|
||||
unusedFunction:fstapi.c:2366
|
||||
|
||||
// These functions are not used by Icarus
|
||||
//unusedFunction:fstapi.c:226
|
||||
|
|
@ -234,59 +234,63 @@ unusedFunction:fastlz.c:150
|
|||
// lz4.c from GTKWave
|
||||
// These functions are not used by Icarus
|
||||
// LZ4_compress_continue()
|
||||
unusedFunction:lz4.c:883
|
||||
unusedFunction:lz4.c:1460
|
||||
// LZ4_compress_destSize()
|
||||
unusedFunction:lz4.c:912
|
||||
// LZ4_compress_fast_force()
|
||||
unusedFunction:lz4.c:705
|
||||
// LZ4_compress_forceExtDict()
|
||||
unusedFunction:lz4.c:895
|
||||
unusedFunction:lz4.c:1063
|
||||
// LZ4_compress_limitedOutput()
|
||||
unusedFunction:lz4.c:730
|
||||
unusedFunction:lz4.c:1455
|
||||
// LZ4_compress_limitedOutput_continue()
|
||||
unusedFunction:lz4.c:888
|
||||
unusedFunction:lz4.c:1459
|
||||
// LZ4_compress_limitedOutput_withState()
|
||||
unusedFunction:lz4.c:1343
|
||||
unusedFunction:lz4.c:1457
|
||||
// LZ4_compress_withState()
|
||||
unusedFunction:lz4.c:1332
|
||||
unusedFunction:lz4.c:1458
|
||||
// LZ4_create()
|
||||
unusedFunction:lz4.c:1314
|
||||
unusedFunction:lz4.c:1489
|
||||
// LZ4_createStream()
|
||||
unusedFunction:lz4.c:765
|
||||
unusedFunction:lz4.c:935
|
||||
// LZ4_createStreamDecode()
|
||||
unusedFunction:lz4.c:1152
|
||||
unusedFunction:lz4.c:1319
|
||||
// LZ4_decompress_fast_continue()
|
||||
unusedFunction:lz4.c:1217
|
||||
unusedFunction:lz4.c:1384
|
||||
// LZ4_decompress_fast_usingDict()
|
||||
unusedFunction:lz4.c:1272
|
||||
unusedFunction:lz4.c:1439
|
||||
// LZ4_decompress_fast_withPrefix64k()
|
||||
unusedFunction:lz4.c:1361
|
||||
unusedFunction:lz4.c:1510
|
||||
// LZ4_decompress_safe_continue()
|
||||
unusedFunction:lz4.c:1188
|
||||
unusedFunction:lz4.c:1355
|
||||
// LZ4_decompress_safe_forceExtDict()
|
||||
unusedFunction:lz4.c:1278
|
||||
unusedFunction:lz4.c:1445
|
||||
// LZ4_decompress_safe_usingDict()
|
||||
unusedFunction:lz4.c:1267
|
||||
unusedFunction:lz4.c:1434
|
||||
// LZ4_decompress_safe_withPrefix64k()
|
||||
unusedFunction:lz4.c:1356
|
||||
unusedFunction:lz4.c:1505
|
||||
// LZ4_freeStream()
|
||||
unusedFunction:lz4.c:773
|
||||
unusedFunction:lz4.c:948
|
||||
// LZ4_freeStreamDecode()
|
||||
unusedFunction:lz4.c:1158
|
||||
unusedFunction:lz4.c:1325
|
||||
// LZ4_loadDict()
|
||||
unusedFunction:lz4.c:780
|
||||
unusedFunction:lz4.c:956
|
||||
// LZ4_resetStreamState()
|
||||
unusedFunction:lz4.c:1307
|
||||
unusedFunction:lz4.c:1482
|
||||
// LZ4_setStreamDecode()
|
||||
unusedFunction:lz4.c:1171
|
||||
unusedFunction:lz4.c:1338
|
||||
// LZ4_sizeofState()
|
||||
unusedFunction:lz4.c:1330
|
||||
unusedFunction:lz4.c:373
|
||||
// LZ4_sizeofStreamState()
|
||||
unusedFunction:lz4.c:1299
|
||||
unusedFunction:lz4.c:1474
|
||||
// LZ4_slideInputBuffer()
|
||||
unusedFunction:lz4.c:1321
|
||||
unusedFunction:lz4.c:1496
|
||||
// LZ4_uncompress()
|
||||
unusedFunction:lz4.c:1293
|
||||
unusedFunction:lz4.c:1468
|
||||
// LZ4_uncompress_unknownOutputSize()
|
||||
unusedFunction:lz4.c:1294
|
||||
unusedFunction:lz4.c:1469
|
||||
// LZ4_versionNumber()
|
||||
unusedFunction:lz4.c:428
|
||||
unusedFunction:lz4.c:371
|
||||
|
||||
// The routines in sys_random.c are exact copies from IEEE1364-2005 and
|
||||
// they have scope warnings that we need to ignore.
|
||||
|
|
|
|||
122
vpi/fstapi.c
122
vpi/fstapi.c
|
|
@ -279,7 +279,6 @@ return(ftruncate(fd, length));
|
|||
static char *fstRealpath(const char *path, char *resolved_path)
|
||||
{
|
||||
#if defined __USE_BSD || defined __USE_XOPEN_EXTENDED || defined __CYGWIN__ || defined HAVE_REALPATH
|
||||
|
||||
#if (defined(__MACH__) && defined(__APPLE__))
|
||||
if(!resolved_path)
|
||||
{
|
||||
|
|
@ -297,6 +296,8 @@ if(!resolved_path)
|
|||
}
|
||||
return(_fullpath(resolved_path, path, PATH_MAX));
|
||||
#else
|
||||
(void)path;
|
||||
(void)resolved_path;
|
||||
return(NULL);
|
||||
#endif
|
||||
#endif
|
||||
|
|
@ -3073,6 +3074,7 @@ uint32_t *rvat_chain_table_lengths;
|
|||
uint64_t rvat_vc_maxhandle;
|
||||
off_t rvat_vc_start;
|
||||
uint32_t *rvat_sig_offs;
|
||||
int rvat_packtype;
|
||||
|
||||
uint32_t rvat_chain_len;
|
||||
unsigned char *rvat_chain_mem;
|
||||
|
|
@ -5885,6 +5887,7 @@ if(frame_uclen == frame_clen)
|
|||
|
||||
xc->rvat_vc_maxhandle = fstReaderVarint64(xc->f);
|
||||
xc->rvat_vc_start = ftello(xc->f); /* points to '!' character */
|
||||
xc->rvat_packtype = fgetc(xc->f);
|
||||
|
||||
#ifdef FST_DEBUG
|
||||
fprintf(stderr, "\tframe_uclen: %d, frame_clen: %d, frame_maxhandle: %d\n",
|
||||
|
|
@ -5909,37 +5912,84 @@ xc->rvat_chain_table_lengths = calloc((xc->rvat_vc_maxhandle+1), sizeof(uint32_t
|
|||
pnt = chain_cmem;
|
||||
idx = 0;
|
||||
pval = 0;
|
||||
do
|
||||
|
||||
if(sectype == FST_BL_VCDATA_DYN_ALIAS2)
|
||||
{
|
||||
int skiplen;
|
||||
uint64_t val = fstGetVarint32(pnt, &skiplen);
|
||||
|
||||
if(!val)
|
||||
{
|
||||
pnt += skiplen;
|
||||
val = fstGetVarint32(pnt, &skiplen);
|
||||
xc->rvat_chain_table[idx] = 0;
|
||||
xc->rvat_chain_table_lengths[idx] = -val;
|
||||
idx++;
|
||||
}
|
||||
else
|
||||
if(val&1)
|
||||
{
|
||||
pval = xc->rvat_chain_table[idx] = pval + (val >> 1);
|
||||
if(idx) { xc->rvat_chain_table_lengths[pidx] = pval - xc->rvat_chain_table[pidx]; }
|
||||
pidx = idx++;
|
||||
}
|
||||
else
|
||||
{
|
||||
fstHandle loopcnt = val >> 1;
|
||||
for(i=0;i<loopcnt;i++)
|
||||
uint32_t prev_alias = 0;
|
||||
|
||||
do {
|
||||
int skiplen;
|
||||
|
||||
if(*pnt & 0x01)
|
||||
{
|
||||
xc->rvat_chain_table[idx++] = 0;
|
||||
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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pnt += skiplen;
|
||||
} while (pnt != (chain_cmem + chain_clen));
|
||||
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;
|
||||
uint64_t val = fstGetVarint32(pnt, &skiplen);
|
||||
|
||||
if(!val)
|
||||
{
|
||||
pnt += skiplen;
|
||||
val = fstGetVarint32(pnt, &skiplen);
|
||||
xc->rvat_chain_table[idx] = 0;
|
||||
xc->rvat_chain_table_lengths[idx] = -val;
|
||||
idx++;
|
||||
}
|
||||
else
|
||||
if(val&1)
|
||||
{
|
||||
pval = xc->rvat_chain_table[idx] = pval + (val >> 1);
|
||||
if(idx) { xc->rvat_chain_table_lengths[pidx] = pval - xc->rvat_chain_table[pidx]; }
|
||||
pidx = idx++;
|
||||
}
|
||||
else
|
||||
{
|
||||
fstHandle loopcnt = val >> 1;
|
||||
for(i=0;i<loopcnt;i++)
|
||||
{
|
||||
xc->rvat_chain_table[idx++] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
pnt += skiplen;
|
||||
} while (pnt != (chain_cmem + chain_clen));
|
||||
}
|
||||
|
||||
free(chain_cmem);
|
||||
xc->rvat_chain_table[idx] = indx_pos - xc->rvat_vc_start;
|
||||
|
|
@ -6003,10 +6053,20 @@ if(!xc->rvat_chain_mem)
|
|||
unsigned char *mc = malloc(xc->rvat_chain_table_lengths[facidx]);
|
||||
unsigned long destlen = xc->rvat_chain_len;
|
||||
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);
|
||||
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);
|
||||
|
||||
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
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
|
|
@ -1029,12 +1029,12 @@ for(i=len;i>0;i--)
|
|||
|
||||
if(!i)
|
||||
{
|
||||
sprintf(tname, "%s_%03d.lxt", lt->lxtname, ++lt->break_number);
|
||||
sprintf(tname, "%s_%03u.lxt", lt->lxtname, ++lt->break_number);
|
||||
}
|
||||
else
|
||||
{
|
||||
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");
|
||||
|
|
|
|||
237
vpi/lz4.h
237
vpi/lz4.h
|
|
@ -1,7 +1,8 @@
|
|||
/*
|
||||
LZ4 - Fast LZ compression algorithm
|
||||
Header File
|
||||
Copyright (C) 2011-2014, Yann Collet.
|
||||
Copyright (C) 2011-2015, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
|
@ -28,7 +29,7 @@
|
|||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
You can contact the author at :
|
||||
- LZ4 source repository : http://code.google.com/p/lz4/
|
||||
- LZ4 source repository : https://github.com/Cyan4973/lz4
|
||||
- LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
|
||||
*/
|
||||
#pragma once
|
||||
|
|
@ -38,22 +39,22 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
/*
|
||||
* lz4.h provides raw compression format functions, for optimal performance and integration into programs.
|
||||
* If you need to generate data using an inter-operable format (respecting the framing specification),
|
||||
* please use lz4frame.h instead.
|
||||
* lz4.h provides block compression functions, and gives full buffer control to programmer.
|
||||
* If you need to generate inter-operable compressed data (respecting LZ4 frame specification),
|
||||
* and can let the library handle its own memory, please use lz4frame.h instead.
|
||||
*/
|
||||
|
||||
/**************************************
|
||||
Version
|
||||
* Version
|
||||
**************************************/
|
||||
#define LZ4_VERSION_MAJOR 1 /* for breaking interface changes */
|
||||
#define LZ4_VERSION_MINOR 5 /* for new (non-breaking) interface capabilities */
|
||||
#define LZ4_VERSION_RELEASE 0 /* for tweaks, bug-fixes, or development */
|
||||
#define LZ4_VERSION_MINOR 7 /* for new (non-breaking) interface capabilities */
|
||||
#define LZ4_VERSION_RELEASE 1 /* for tweaks, bug-fixes, or development */
|
||||
#define LZ4_VERSION_NUMBER (LZ4_VERSION_MAJOR *100*100 + LZ4_VERSION_MINOR *100 + LZ4_VERSION_RELEASE)
|
||||
int LZ4_versionNumber (void);
|
||||
|
||||
/**************************************
|
||||
Tuning parameter
|
||||
* Tuning parameter
|
||||
**************************************/
|
||||
/*
|
||||
* LZ4_MEMORY_USAGE :
|
||||
|
|
@ -66,77 +67,90 @@ int LZ4_versionNumber (void);
|
|||
|
||||
|
||||
/**************************************
|
||||
Simple Functions
|
||||
* Simple Functions
|
||||
**************************************/
|
||||
|
||||
int LZ4_compress (const char* source, char* dest, int sourceSize);
|
||||
int LZ4_compress_default(const char* source, char* dest, int sourceSize, int maxDestSize);
|
||||
int LZ4_decompress_safe (const char* source, char* dest, int compressedSize, int maxDecompressedSize);
|
||||
|
||||
/*
|
||||
LZ4_compress() :
|
||||
Compresses 'sourceSize' bytes from 'source' into 'dest'.
|
||||
Destination buffer must be already allocated,
|
||||
and must be sized to handle worst cases situations (input data not compressible)
|
||||
Worst case size evaluation is provided by function LZ4_compressBound()
|
||||
inputSize : Max supported value is LZ4_MAX_INPUT_SIZE
|
||||
return : the number of bytes written in buffer dest
|
||||
or 0 if the compression fails
|
||||
LZ4_compress_default() :
|
||||
Compresses 'sourceSize' bytes from buffer 'source'
|
||||
into already allocated 'dest' buffer of size 'maxDestSize'.
|
||||
Compression is guaranteed to succeed if 'maxDestSize' >= LZ4_compressBound(sourceSize).
|
||||
It also runs faster, so it's a recommended setting.
|
||||
If the function cannot compress 'source' into a more limited 'dest' budget,
|
||||
compression stops *immediately*, and the function result is zero.
|
||||
As a consequence, 'dest' content is not valid.
|
||||
This function never writes outside 'dest' buffer, nor read outside 'source' buffer.
|
||||
sourceSize : Max supported value is LZ4_MAX_INPUT_VALUE
|
||||
maxDestSize : full or partial size of buffer 'dest' (which must be already allocated)
|
||||
return : the number of bytes written into buffer 'dest' (necessarily <= maxOutputSize)
|
||||
or 0 if compression fails
|
||||
|
||||
LZ4_decompress_safe() :
|
||||
compressedSize : is obviously the source size
|
||||
maxDecompressedSize : is the size of the destination buffer, which must be already allocated.
|
||||
return : the number of bytes decompressed into the destination buffer (necessarily <= maxDecompressedSize)
|
||||
If the destination buffer is not large enough, decoding will stop and output an error code (<0).
|
||||
compressedSize : is the precise full size of the compressed block.
|
||||
maxDecompressedSize : is the size of destination buffer, which must be already allocated.
|
||||
return : the number of bytes decompressed into destination buffer (necessarily <= maxDecompressedSize)
|
||||
If destination buffer is not large enough, decoding will stop and output an error code (<0).
|
||||
If the source stream is detected malformed, the function will stop decoding and return a negative result.
|
||||
This function is protected against buffer overflow exploits,
|
||||
and never writes outside of output buffer, nor reads outside of input buffer.
|
||||
It is also protected against malicious data packets.
|
||||
This function is protected against buffer overflow exploits, including malicious data packets.
|
||||
It never writes outside output buffer, nor reads outside input buffer.
|
||||
*/
|
||||
|
||||
|
||||
/**************************************
|
||||
Advanced Functions
|
||||
* Advanced Functions
|
||||
**************************************/
|
||||
#define LZ4_MAX_INPUT_SIZE 0x7E000000 /* 2 113 929 216 bytes */
|
||||
#define LZ4_COMPRESSBOUND(isize) ((unsigned int)(isize) > (unsigned int)LZ4_MAX_INPUT_SIZE ? 0 : (isize) + ((isize)/255) + 16)
|
||||
#define LZ4_COMPRESSBOUND(isize) ((unsigned)(isize) > (unsigned)LZ4_MAX_INPUT_SIZE ? 0 : (isize) + ((isize)/255) + 16)
|
||||
|
||||
/*
|
||||
LZ4_compressBound() :
|
||||
Provides the maximum size that LZ4 compression may output in a "worst case" scenario (input data not compressible)
|
||||
This function is primarily useful for memory allocation purposes (output buffer size).
|
||||
This function is primarily useful for memory allocation purposes (destination buffer size).
|
||||
Macro LZ4_COMPRESSBOUND() is also provided for compilation-time evaluation (stack memory allocation for example).
|
||||
|
||||
isize : is the input size. Max supported value is LZ4_MAX_INPUT_SIZE
|
||||
return : maximum output size in a "worst case" scenario
|
||||
or 0, if input size is too large ( > LZ4_MAX_INPUT_SIZE)
|
||||
Note that LZ4_compress_default() compress faster when dest buffer size is >= LZ4_compressBound(srcSize)
|
||||
inputSize : max supported value is LZ4_MAX_INPUT_SIZE
|
||||
return : maximum output size in a "worst case" scenario
|
||||
or 0, if input size is too large ( > LZ4_MAX_INPUT_SIZE)
|
||||
*/
|
||||
int LZ4_compressBound(int isize);
|
||||
int LZ4_compressBound(int inputSize);
|
||||
|
||||
/*
|
||||
LZ4_compress_fast() :
|
||||
Same as LZ4_compress_default(), but allows to select an "acceleration" factor.
|
||||
The larger the acceleration value, the faster the algorithm, but also the lesser the compression.
|
||||
It's a trade-off. It can be fine tuned, with each successive value providing roughly +~3% to speed.
|
||||
An acceleration value of "1" is the same as regular LZ4_compress_default()
|
||||
Values <= 0 will be replaced by ACCELERATION_DEFAULT (see lz4.c), which is 1.
|
||||
*/
|
||||
int LZ4_compress_fast (const char* source, char* dest, int sourceSize, int maxDestSize, int acceleration);
|
||||
|
||||
|
||||
/*
|
||||
LZ4_compress_limitedOutput() :
|
||||
Compress 'sourceSize' bytes from 'source' into an output buffer 'dest' of maximum size 'maxOutputSize'.
|
||||
If it cannot achieve it, compression will stop, and result of the function will be zero.
|
||||
This saves time and memory on detecting non-compressible (or barely compressible) data.
|
||||
This function never writes outside of provided output buffer.
|
||||
|
||||
sourceSize : Max supported value is LZ4_MAX_INPUT_VALUE
|
||||
maxOutputSize : is the size of the destination buffer (which must be already allocated)
|
||||
return : the number of bytes written in buffer 'dest'
|
||||
or 0 if compression fails
|
||||
*/
|
||||
int LZ4_compress_limitedOutput (const char* source, char* dest, int sourceSize, int maxOutputSize);
|
||||
|
||||
|
||||
/*
|
||||
LZ4_compress_withState() :
|
||||
Same compression functions, but using an externally allocated memory space to store compression state.
|
||||
LZ4_compress_fast_extState() :
|
||||
Same compression function, just using an externally allocated memory space to store compression state.
|
||||
Use LZ4_sizeofState() to know how much memory must be allocated,
|
||||
and then, provide it as 'void* state' to compression functions.
|
||||
and allocate it on 8-bytes boundaries (using malloc() typically).
|
||||
Then, provide it as 'void* state' to compression function.
|
||||
*/
|
||||
int LZ4_sizeofState(void);
|
||||
int LZ4_compress_withState (void* state, const char* source, char* dest, int inputSize);
|
||||
int LZ4_compress_limitedOutput_withState (void* state, const char* source, char* dest, int inputSize, int maxOutputSize);
|
||||
int LZ4_compress_fast_extState (void* state, const char* source, char* dest, int inputSize, int maxDestSize, int acceleration);
|
||||
|
||||
|
||||
/*
|
||||
LZ4_compress_destSize() :
|
||||
Reverse the logic, by compressing as much data as possible from 'source' buffer
|
||||
into already allocated buffer 'dest' of size 'targetDestSize'.
|
||||
This function either compresses the entire 'source' content into 'dest' if it's large enough,
|
||||
or fill 'dest' buffer completely with as much data as possible from 'source'.
|
||||
*sourceSizePtr : will be modified to indicate how many bytes where read from 'source' to fill 'dest'.
|
||||
New value is necessarily <= old value.
|
||||
return : Nb bytes written into 'dest' (necessarily <= targetDestSize)
|
||||
or 0 if compression fails
|
||||
*/
|
||||
int LZ4_compress_destSize (const char* source, char* dest, int* sourceSizePtr, int targetDestSize);
|
||||
|
||||
|
||||
/*
|
||||
|
|
@ -152,7 +166,6 @@ LZ4_decompress_fast() :
|
|||
*/
|
||||
int LZ4_decompress_fast (const char* source, char* dest, int originalSize);
|
||||
|
||||
|
||||
/*
|
||||
LZ4_decompress_safe_partial() :
|
||||
This function decompress a compressed block of size 'compressedSize' at position 'source'
|
||||
|
|
@ -169,9 +182,8 @@ int LZ4_decompress_safe_partial (const char* source, char* dest, int compressedS
|
|||
|
||||
|
||||
/***********************************************
|
||||
Streaming Compression Functions
|
||||
* Streaming Compression Functions
|
||||
***********************************************/
|
||||
|
||||
#define LZ4_STREAMSIZE_U64 ((1 << (LZ4_MEMORY_USAGE-3)) + 4)
|
||||
#define LZ4_STREAMSIZE (LZ4_STREAMSIZE_U64 * sizeof(long long))
|
||||
/*
|
||||
|
|
@ -187,7 +199,7 @@ typedef struct { long long table[LZ4_STREAMSIZE_U64]; } LZ4_stream_t;
|
|||
* LZ4_resetStream
|
||||
* Use this function to init an allocated LZ4_stream_t structure
|
||||
*/
|
||||
void LZ4_resetStream (LZ4_stream_t* LZ4_streamPtr);
|
||||
void LZ4_resetStream (LZ4_stream_t* streamPtr);
|
||||
|
||||
/*
|
||||
* LZ4_createStream will allocate and initialize an LZ4_stream_t structure
|
||||
|
|
@ -196,7 +208,7 @@ void LZ4_resetStream (LZ4_stream_t* LZ4_streamPtr);
|
|||
* They are more future proof, in case of a change of LZ4_stream_t size.
|
||||
*/
|
||||
LZ4_stream_t* LZ4_createStream(void);
|
||||
int LZ4_freeStream (LZ4_stream_t* LZ4_streamPtr);
|
||||
int LZ4_freeStream (LZ4_stream_t* streamPtr);
|
||||
|
||||
/*
|
||||
* LZ4_loadDict
|
||||
|
|
@ -205,36 +217,31 @@ int LZ4_freeStream (LZ4_stream_t* LZ4_streamPtr);
|
|||
* Loading a size of 0 is allowed.
|
||||
* Return : dictionary size, in bytes (necessarily <= 64 KB)
|
||||
*/
|
||||
int LZ4_loadDict (LZ4_stream_t* LZ4_streamPtr, const char* dictionary, int dictSize);
|
||||
int LZ4_loadDict (LZ4_stream_t* streamPtr, const char* dictionary, int dictSize);
|
||||
|
||||
/*
|
||||
* LZ4_compress_continue
|
||||
* Compress data block 'source', using blocks compressed before as dictionary to improve compression ratio
|
||||
* Previous data blocks are assumed to still be present at their previous location.
|
||||
* LZ4_compress_fast_continue
|
||||
* Compress buffer content 'src', using data from previously compressed blocks as dictionary to improve compression ratio.
|
||||
* Important : Previous data blocks are assumed to still be present and unmodified !
|
||||
* 'dst' buffer must be already allocated.
|
||||
* If maxDstSize >= LZ4_compressBound(srcSize), compression is guaranteed to succeed, and runs faster.
|
||||
* If not, and if compressed data cannot fit into 'dst' buffer size, compression stops, and function returns a zero.
|
||||
*/
|
||||
int LZ4_compress_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize);
|
||||
|
||||
/*
|
||||
* LZ4_compress_limitedOutput_continue
|
||||
* Same as before, but also specify a maximum target compressed size (maxOutputSize)
|
||||
* If objective cannot be met, compression exits, and returns a zero.
|
||||
*/
|
||||
int LZ4_compress_limitedOutput_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize, int maxOutputSize);
|
||||
int LZ4_compress_fast_continue (LZ4_stream_t* streamPtr, const char* src, char* dst, int srcSize, int maxDstSize, int acceleration);
|
||||
|
||||
/*
|
||||
* LZ4_saveDict
|
||||
* If previously compressed data block is not guaranteed to remain available at its memory location
|
||||
* save it into a safer place (char* safeBuffer)
|
||||
* Note : you don't need to call LZ4_loadDict() afterwards,
|
||||
* dictionary is immediately usable, you can therefore call again LZ4_compress_continue()
|
||||
* Return : dictionary size in bytes, or 0 if error
|
||||
* Note : any dictSize > 64 KB will be interpreted as 64KB.
|
||||
* dictionary is immediately usable, you can therefore call LZ4_compress_fast_continue()
|
||||
* Return : saved dictionary size in bytes (necessarily <= dictSize), or 0 if error
|
||||
*/
|
||||
int LZ4_saveDict (LZ4_stream_t* LZ4_streamPtr, char* safeBuffer, int dictSize);
|
||||
int LZ4_saveDict (LZ4_stream_t* streamPtr, char* safeBuffer, int dictSize);
|
||||
|
||||
|
||||
/************************************************
|
||||
Streaming Decompression Functions
|
||||
* Streaming Decompression Functions
|
||||
************************************************/
|
||||
|
||||
#define LZ4_STREAMDECODESIZE_U64 4
|
||||
|
|
@ -265,8 +272,18 @@ int LZ4_setStreamDecode (LZ4_streamDecode_t* LZ4_streamDecode, const char* dicti
|
|||
*_continue() :
|
||||
These decoding functions allow decompression of multiple blocks in "streaming" mode.
|
||||
Previously decoded blocks *must* remain available at the memory position where they were decoded (up to 64 KB)
|
||||
If this condition is not possible, save the relevant part of decoded data into a safe buffer,
|
||||
and indicate where is its new address using LZ4_setStreamDecode()
|
||||
In the case of a ring buffers, decoding buffer must be either :
|
||||
- Exactly same size as encoding buffer, with same update rule (block boundaries at same positions)
|
||||
In which case, the decoding & encoding ring buffer can have any size, including very small ones ( < 64 KB).
|
||||
- Larger than encoding buffer, by a minimum of maxBlockSize more bytes.
|
||||
maxBlockSize is implementation dependent. It's the maximum size you intend to compress into a single block.
|
||||
In which case, encoding and decoding buffers do not need to be synchronized,
|
||||
and encoding ring buffer can have any size, including small ones ( < 64 KB).
|
||||
- _At least_ 64 KB + 8 bytes + maxBlockSize.
|
||||
In which case, encoding and decoding buffers do not need to be synchronized,
|
||||
and encoding ring buffer can have any size, including larger than decoding buffer.
|
||||
Whenever these conditions are not possible, save the last 64KB of decoded data into a safe buffer,
|
||||
and indicate where it is saved using LZ4_setStreamDecode()
|
||||
*/
|
||||
int LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int compressedSize, int maxDecompressedSize);
|
||||
int LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int originalSize);
|
||||
|
|
@ -276,8 +293,8 @@ int LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode, const ch
|
|||
Advanced decoding functions :
|
||||
*_usingDict() :
|
||||
These decoding functions work the same as
|
||||
a combination of LZ4_setDictDecode() followed by LZ4_decompress_x_continue()
|
||||
They are stand-alone and don't use nor update an LZ4_streamDecode_t structure.
|
||||
a combination of LZ4_setStreamDecode() followed by LZ4_decompress_x_continue()
|
||||
They are stand-alone. They don't need nor update an LZ4_streamDecode_t structure.
|
||||
*/
|
||||
int LZ4_decompress_safe_usingDict (const char* source, char* dest, int compressedSize, int maxDecompressedSize, const char* dictStart, int dictSize);
|
||||
int LZ4_decompress_fast_usingDict (const char* source, char* dest, int originalSize, const char* dictStart, int dictSize);
|
||||
|
|
@ -285,29 +302,57 @@ int LZ4_decompress_fast_usingDict (const char* source, char* dest, int originalS
|
|||
|
||||
|
||||
/**************************************
|
||||
Obsolete Functions
|
||||
* Obsolete Functions
|
||||
**************************************/
|
||||
/*
|
||||
Obsolete decompression functions
|
||||
These function names are deprecated and should no longer be used.
|
||||
They are only provided here for compatibility with older user programs.
|
||||
- LZ4_uncompress is the same as LZ4_decompress_fast
|
||||
- LZ4_uncompress_unknownOutputSize is the same as LZ4_decompress_safe
|
||||
These function prototypes are now disabled; uncomment them if you really need them.
|
||||
It is highly recommended to stop using these functions and migrate to newer ones */
|
||||
/* Deprecate Warnings */
|
||||
/* Should these warnings messages be a problem,
|
||||
it is generally possible to disable them,
|
||||
with -Wno-deprecated-declarations for gcc
|
||||
or _CRT_SECURE_NO_WARNINGS in Visual for example.
|
||||
You can also define LZ4_DEPRECATE_WARNING_DEFBLOCK. */
|
||||
#ifndef LZ4_DEPRECATE_WARNING_DEFBLOCK
|
||||
# define LZ4_DEPRECATE_WARNING_DEFBLOCK
|
||||
# define LZ4_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
|
||||
# if (LZ4_GCC_VERSION >= 405) || defined(__clang__)
|
||||
# define LZ4_DEPRECATED(message) __attribute__((deprecated(message)))
|
||||
# elif (LZ4_GCC_VERSION >= 301)
|
||||
# define LZ4_DEPRECATED(message) __attribute__((deprecated))
|
||||
# elif defined(_MSC_VER)
|
||||
# define LZ4_DEPRECATED(message) __declspec(deprecated(message))
|
||||
# else
|
||||
# pragma message("WARNING: You need to implement LZ4_DEPRECATED for this compiler")
|
||||
# define LZ4_DEPRECATED(message)
|
||||
# endif
|
||||
#endif /* LZ4_DEPRECATE_WARNING_DEFBLOCK */
|
||||
|
||||
/* Obsolete compression functions */
|
||||
/* These functions are planned to start generate warnings by r131 approximately */
|
||||
int LZ4_compress (const char* source, char* dest, int sourceSize);
|
||||
int LZ4_compress_limitedOutput (const char* source, char* dest, int sourceSize, int maxOutputSize);
|
||||
int LZ4_compress_withState (void* state, const char* source, char* dest, int inputSize);
|
||||
int LZ4_compress_limitedOutput_withState (void* state, const char* source, char* dest, int inputSize, int maxOutputSize);
|
||||
int LZ4_compress_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize);
|
||||
int LZ4_compress_limitedOutput_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize, int maxOutputSize);
|
||||
|
||||
/* Obsolete decompression functions */
|
||||
/* These function names are completely deprecated and must no longer be used.
|
||||
They are only provided here for compatibility with older programs.
|
||||
- LZ4_uncompress is the same as LZ4_decompress_fast
|
||||
- LZ4_uncompress_unknownOutputSize is the same as LZ4_decompress_safe
|
||||
These function prototypes are now disabled; uncomment them only if you really need them.
|
||||
It is highly recommended to stop using these prototypes and migrate to maintained ones */
|
||||
/* int LZ4_uncompress (const char* source, char* dest, int outputSize); */
|
||||
/* int LZ4_uncompress_unknownOutputSize (const char* source, char* dest, int isize, int maxOutputSize); */
|
||||
|
||||
|
||||
/* Obsolete streaming functions; use new streaming interface whenever possible */
|
||||
void* LZ4_create (const char* inputBuffer);
|
||||
int LZ4_sizeofStreamState(void);
|
||||
int LZ4_resetStreamState(void* state, const char* inputBuffer);
|
||||
char* LZ4_slideInputBuffer (void* state);
|
||||
LZ4_DEPRECATED("use LZ4_createStream() instead") void* LZ4_create (char* inputBuffer);
|
||||
LZ4_DEPRECATED("use LZ4_createStream() instead") int LZ4_sizeofStreamState(void);
|
||||
LZ4_DEPRECATED("use LZ4_resetStream() instead") int LZ4_resetStreamState(void* state, char* inputBuffer);
|
||||
LZ4_DEPRECATED("use LZ4_saveDict() instead") char* LZ4_slideInputBuffer (void* state);
|
||||
|
||||
/* Obsolete streaming decoding functions */
|
||||
int LZ4_decompress_safe_withPrefix64k (const char* source, char* dest, int compressedSize, int maxOutputSize);
|
||||
int LZ4_decompress_fast_withPrefix64k (const char* source, char* dest, int originalSize);
|
||||
LZ4_DEPRECATED("use LZ4_decompress_safe_usingDict() instead") int LZ4_decompress_safe_withPrefix64k (const char* src, char* dst, int compressedSize, int maxDstSize);
|
||||
LZ4_DEPRECATED("use LZ4_decompress_fast_usingDict() instead") int LZ4_decompress_fast_withPrefix64k (const char* src, char* dst, int originalSize);
|
||||
|
||||
|
||||
#if defined (__cplusplus)
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ static void my_mcd_rawwrite(PLI_UINT32 mcd, const char*buf, size_t count)
|
|||
if (fp) {
|
||||
while (count > 0) {
|
||||
size_t rc = fwrite(buf, 1, count, fp);
|
||||
if (rc <= 0) break;
|
||||
if (rc == 0) break;
|
||||
count -= rc;
|
||||
buf += rc;
|
||||
}
|
||||
|
|
@ -1971,12 +1971,7 @@ static PLI_INT32 sys_printtimescale_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
|
|||
item = vpi_scan(argv);
|
||||
vpi_free_object(argv);
|
||||
}
|
||||
|
||||
if (vpi_get(vpiType, item) != vpiModule) {
|
||||
scope = vpi_handle(vpiModule, item);
|
||||
} else {
|
||||
scope = item;
|
||||
}
|
||||
scope = sys_func_module(item);
|
||||
|
||||
vpi_printf("Time scale of (%s) is ", vpi_get_str(vpiFullName, item));
|
||||
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);
|
||||
|
||||
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),
|
||||
name);
|
||||
vpi_control(vpiFinish, 1);
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue