Merge branch 'master' into cross_compile

This commit is contained in:
Stephen Williams 2019-03-24 10:27:33 -07:00 committed by GitHub
commit c3575d379b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
168 changed files with 5710 additions and 2533 deletions

View File

@ -116,13 +116,17 @@ programs.
RESEARCHING EXISTING/PAST BUGS, AND FILING REPORTS
The URL <http://sourceforge.net/tracker/?group_id=149850> is the main
bug tracking system. Once you believe you have found a bug, you may
browse the bugs database for existing bugs that may be related to
yours. You might find that your bug has already been fixed in a later
release or snapshot. If that's the case, then you are set. Also,
consider if you are reporting a bug or really asking for a new
feature, and use the appropriate tracker.
The URL <https://sourceforge.net/p/iverilog/bugs/> is the main
bug tracking system, although some users have reported bugs at
<https://github.com/steveicarus/iverilog/issues/>. Once you believe
you have found a bug, you may browse the bugs database for existing
bugs that may be related to yours. You might find that your bug has
already been fixed in a later release or snapshot. If that's the case,
then you are set. Also, consider if you are reporting a bug or really
asking for a new feature, and use the appropriate tracker.
system (although you will also find bug rep
The bug database supports basic keyword searches, and you can
optionally limit your search to active bugs, or fixed bugs. You may
@ -145,7 +149,7 @@ version from git. Please see the developer documentation for more
detailed instructions -- <http://iverilog.wikia.com/wiki/>.
When you make a patch, submit it to the "Patches" tracker at
<http://sourceforge.net/tracker/?group_id=149850>. Patches added to
<https://sourceforge.net/p/iverilog/patches/>. Patches added to
the "Patches" tracker enter the developer workflow, are checked,
applied to the appropriate git branch, and are pushed. Then the
tracker item is closed.
@ -158,7 +162,7 @@ clarification before applying it.)
COPYRIGHT ISSUES
Icarus Verilog is Copyright (c) 1998-2008 Stephen Williams except
Icarus Verilog is Copyright (c) 1998-2018 Stephen Williams except
where otherwise noted. Minor patches are covered as derivative works
(or editorial comment or whatever the appropriate legal term is) and
folded into the rest of ivl. However, if a submission can reasonably

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2016 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-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
@ -35,7 +35,6 @@ Module::Module(LexicalScope*parent, perm_string n)
is_interface = false;
program_block = false;
uc_drive = UCD_NONE;
timescale_warn_done = false;
}
Module::~Module()

View File

@ -1,7 +1,7 @@
#ifndef IVL_Module_H
#define IVL_Module_H
/*
* Copyright (c) 1998-2016 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-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
@ -121,8 +121,6 @@ class Module : public PScopeExtra, public LineInfo {
map<perm_string,PExpr*> attributes;
bool timescale_warn_done;
/* The module has a list of generate schemes that appear in
the module definition. These are used at elaboration time. */
list<PGenerate*> generate_schemes;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2011 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-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
@ -26,11 +26,6 @@
# include "verinum.h"
# include "netmisc.h"
bool dly_used_no_timescale = false;
bool dly_used_timescale = false;
bool display_ts_dly_warning = true;
PDelays::PDelays()
{
delete_flag_ = true;
@ -80,19 +75,7 @@ static NetExpr*calculate_val(Design*des, NetScope*scope, PExpr*expr)
{
NetExpr*dex = elab_and_eval(des, scope, expr, -1);
/* Print a warning if we find default and `timescale based
* delays in the design, since this is likely an error. */
if (scope->time_from_timescale()) dly_used_timescale = true;
else dly_used_no_timescale = true;
if (display_ts_dly_warning &&
dly_used_no_timescale && dly_used_timescale) {
cerr << "warning: Found both default and "
"`timescale based delays. Use" << endl;
cerr << " -Wtimescale to find the "
"module(s) with no `timescale." << endl;
display_ts_dly_warning = false;
}
check_for_inconsistent_delays(scope);
/* If the delay expression is a real constant or vector
constant, then evaluate it, scale it to the local time

View File

@ -217,6 +217,8 @@ class PGModule : public PGate {
// method to pass the range to the pform.
void set_range(PExpr*msb, PExpr*lsb);
map<perm_string,PExpr*> attributes;
virtual void dump(ostream&out, unsigned ind =4) const;
virtual void elaborate(Design*, NetScope*scope) const;
virtual void elaborate_scope(Design*des, NetScope*sc) const;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008,2016 Stephen Williams (steve@icarus.com)
* Copyright (c) 2008-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
@ -38,7 +38,8 @@ PScope::PScope(perm_string n, LexicalScope*parent)
{
time_unit = 0;
time_precision = 0;
time_from_timescale = false;
time_unit_is_default = true;
time_prec_is_default = true;
}
PScope::~PScope()
@ -51,6 +52,8 @@ PScope::~PScope()
PScopeExtra::PScopeExtra(perm_string n, LexicalScope*parent)
: PScope(n, parent)
{
time_unit_is_local = false;
time_prec_is_local = false;
}
PScopeExtra::~PScopeExtra()

View File

@ -1,7 +1,7 @@
#ifndef IVL_PScope_H
#define IVL_PScope_H
/*
* Copyright (c) 2008-2016 Stephen Williams (steve@icarus.com)
* Copyright (c) 2008-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
@ -164,11 +164,18 @@ class PScope : public LexicalScope {
perm_string pscope_name() const { return name_; }
/* These are the timescale for this scope. The default is
/* These are the timescale for this scope. The value is
set by the `timescale directive or, in SystemVerilog,
by timeunit and timeprecision statements. */
int time_unit, time_precision;
bool time_from_timescale;
/* Flags used to support warnings about timescales. */
bool time_unit_is_default;
bool time_prec_is_default;
bool has_explicit_timescale() const {
return !(time_unit_is_default || time_prec_is_default);
}
protected:
bool elaborate_sig_wires_(Design*des, NetScope*scope) const;
@ -199,6 +206,10 @@ class PScopeExtra : public PScope {
elaboration to choose an elaboration order. */
std::vector<PClass*> classes_lexical;
/* Flags used to support warnings about timescales. */
bool time_unit_is_local;
bool time_prec_is_local;
protected:
void dump_classes_(ostream&out, unsigned indent) const;
void dump_tasks_(ostream&out, unsigned indent) const;

View File

@ -1,5 +1,5 @@
THE ICARUS VERILOG COMPILATION SYSTEM
Copyright 2000-2004 Stephen Williams
Copyright 2000-2019 Stephen Williams
1.0 What is ICARUS Verilog?
@ -47,7 +47,7 @@ on a UNIX-like system:
- bison and flex
- gperf 2.7
- gperf 2.7 or later
The lexical analyzer doesn't recognize keywords directly,
but instead matches symbols and looks them up in a hash
table in order to get the proper lexical code. The gperf
@ -56,7 +56,7 @@ on a UNIX-like system:
A version problem with this program is the most common cause
of difficulty. See the Icarus Verilog FAQ.
- readline 4.2
- readline 4.2 or later
On Linux systems, this usually means the readline-devel
rpm. In any case, it is the development headers of readline
that are needed.
@ -67,7 +67,7 @@ on a UNIX-like system:
If you are building from git, you will also need software to generate
the configure scripts.
- autoconf 2.53
- autoconf 2.53 or later
This generates configure scripts from configure.in. The 2.53
or later versions are known to work, autoconf 2.13 is
reported to *not* work.
@ -81,6 +81,12 @@ with the commands:
./configure
make
If you are building from git, you have to run the command below before
compile the source. This will generate the "configure" file, which is
automatically done when building from tarball.
sh autoconf.sh
Normally, this command automatically figures out everything it needs
to know. It generally works pretty well. There are a few flags to the
configure script that modify its behavior:

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2013 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-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
@ -294,20 +294,20 @@ PDoWhile::~PDoWhile()
}
PEventStatement::PEventStatement(const svector<PEEvent*>&ee)
: expr_(ee), statement_(0)
: expr_(ee), statement_(0), search_funcs_(false)
{
assert(expr_.count() > 0);
}
PEventStatement::PEventStatement(PEEvent*ee)
: expr_(1), statement_(0)
: expr_(1), statement_(0), search_funcs_(false)
{
expr_[0] = ee;
}
PEventStatement::PEventStatement(void)
: statement_(0)
PEventStatement::PEventStatement(bool search_funcs)
: statement_(0), search_funcs_(search_funcs)
{
}

View File

@ -1,7 +1,7 @@
#ifndef IVL_Statement_H
#define IVL_Statement_H
/*
* Copyright (c) 1998-2014 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-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
@ -402,8 +402,9 @@ class PEventStatement : public Statement {
explicit PEventStatement(const svector<PEEvent*>&ee);
explicit PEventStatement(PEEvent*ee);
// Make an @* statement.
explicit PEventStatement(void);
// Make an @* statement or make a special @* version with the items
// from functions added and ouputs removed for always_comb/latch.
explicit PEventStatement(bool search_funcs = false);
~PEventStatement();
@ -429,6 +430,7 @@ class PEventStatement : public Statement {
private:
svector<PEEvent*>expr_;
Statement*statement_;
bool search_funcs_;
};
ostream& operator << (ostream&o, const PEventStatement&obj);

View File

@ -1,7 +1,7 @@
#ifndef IVL_compiler_H
#define IVL_compiler_H
/*
* Copyright (c) 1999-2016 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-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
@ -117,6 +117,13 @@ extern bool debug_emit;
extern bool debug_synth2;
extern bool debug_optimizer;
/* Ignore errors about missing modules */
extern bool ignore_missing_modules;
/* Treat each source file as a separate compilation unit (as defined
by SystemVerilog). */
extern bool separate_compilation;
/* Control evaluation of functions at compile time:
* 0 = only for functions in constant expressions
* 1 = only for automatic functions

View File

@ -1,613 +1,619 @@
// These are correct and are used to find the base (zero) pin.
thisSubtraction:netlist.h:5081
thisSubtraction:netlist.h:5090
thisSubtraction:netlist.h:5082
thisSubtraction:netlist.h:5091
// These are the functions that the compiler exports to the targets.
//ivl_branch_island()
unusedFunction:t-dll-api.cc:38
unusedFunction:t-dll-api.cc:39
//ivl_branch_terminal()
unusedFunction:t-dll-api.cc:43
unusedFunction:t-dll-api.cc:45
//ivl_const_bits()
unusedFunction:t-dll-api.cc:180
unusedFunction:t-dll-api.cc:196
//ivl_const_delay()
unusedFunction:t-dll-api.cc:198
unusedFunction:t-dll-api.cc:214
//ivl_const_file()
unusedFunction:t-dll-api.cc:204
unusedFunction:t-dll-api.cc:221
//ivl_const_lineno()
unusedFunction:t-dll-api.cc:210
unusedFunction:t-dll-api.cc:227
//ivl_const_nex()
unusedFunction:t-dll-api.cc:216
unusedFunction:t-dll-api.cc:233
//ivl_const_real()
unusedFunction:t-dll-api.cc:222
unusedFunction:t-dll-api.cc:239
//ivl_const_scope()
unusedFunction:t-dll-api.cc:229
unusedFunction:t-dll-api.cc:246
//ivl_const_signed()
unusedFunction:t-dll-api.cc:235
unusedFunction:t-dll-api.cc:252
//ivl_const_type()
unusedFunction:t-dll-api.cc:174
unusedFunction:t-dll-api.cc:190
//ivl_const_width()
unusedFunction:t-dll-api.cc:241
unusedFunction:t-dll-api.cc:258
//ivl_design_const()
unusedFunction:t-dll-api.cc:116
unusedFunction:t-dll-api.cc:127
//ivl_design_consts()
unusedFunction:t-dll-api.cc:111
unusedFunction:t-dll-api.cc:121
//ivl_design_delay_sel()
unusedFunction:t-dll-api.cc:49
unusedFunction:t-dll-api.cc:52
//ivl_design_discipline()
unusedFunction:t-dll-api.cc:128
unusedFunction:t-dll-api.cc:140
//ivl_design_disciplines()
unusedFunction:t-dll-api.cc:122
unusedFunction:t-dll-api.cc:134
//ivl_design_flag()
unusedFunction:t-dll-api.cc:54
//ivl_design_process()
unusedFunction:t-dll-api.cc:59
//ivl_design_process()
unusedFunction:t-dll-api.cc:66
//ivl_design_root()
unusedFunction:t-dll-api.cc:72
unusedFunction:t-dll-api.cc:80
//ivl_design_roots()
unusedFunction:t-dll-api.cc:81
unusedFunction:t-dll-api.cc:89
//ivl_design_time_precision()
unusedFunction:t-dll-api.cc:106
unusedFunction:t-dll-api.cc:115
//ivl_discipline_domain()
unusedFunction:t-dll-api.cc:135
unusedFunction:t-dll-api.cc:147
//ivl_discipline_flow()
unusedFunction:t-dll-api.cc:140
unusedFunction:t-dll-api.cc:153
//ivl_discipline_name()
unusedFunction:t-dll-api.cc:145
unusedFunction:t-dll-api.cc:159
//ivl_discipline_potential()
unusedFunction:t-dll-api.cc:150
unusedFunction:t-dll-api.cc:165
//ivl_enum_bits()
unusedFunction:t-dll-api.cc:260
unusedFunction:t-dll-api.cc:277
//ivl_enum_file()
unusedFunction:t-dll-api.cc:285
unusedFunction:t-dll-api.cc:302
//ivl_enum_lineno()
unusedFunction:t-dll-api.cc:291
unusedFunction:t-dll-api.cc:308
//ivl_enum_name()
unusedFunction:t-dll-api.cc:253
unusedFunction:t-dll-api.cc:270
//ivl_enum_names()
unusedFunction:t-dll-api.cc:247
unusedFunction:t-dll-api.cc:264
//ivl_enum_signed()
unusedFunction:t-dll-api.cc:279
unusedFunction:t-dll-api.cc:296
//ivl_enum_type()
unusedFunction:t-dll-api.cc:267
unusedFunction:t-dll-api.cc:284
//ivl_enum_width()
unusedFunction:t-dll-api.cc:273
unusedFunction:t-dll-api.cc:290
//ivl_event_any()
unusedFunction:t-dll-api.cc:349
//ivl_event_file()
unusedFunction:t-dll-api.cc:326
//ivl_event_lineno()
unusedFunction:t-dll-api.cc:332
//ivl_event_name()
unusedFunction:t-dll-api.cc:297
//ivl_event_nany()
unusedFunction:t-dll-api.cc:343
//ivl_event_neg()
unusedFunction:t-dll-api.cc:362
//ivl_event_nneg()
unusedFunction:t-dll-api.cc:356
//ivl_event_npos()
unusedFunction:t-dll-api.cc:369
//ivl_event_file()
unusedFunction:t-dll-api.cc:345
//ivl_event_lineno()
unusedFunction:t-dll-api.cc:351
//ivl_event_name()
unusedFunction:t-dll-api.cc:314
//ivl_event_nany()
unusedFunction:t-dll-api.cc:363
//ivl_event_neg()
unusedFunction:t-dll-api.cc:382
//ivl_event_nneg()
unusedFunction:t-dll-api.cc:376
//ivl_event_npos()
unusedFunction:t-dll-api.cc:389
//ivl_event_pos()
unusedFunction:t-dll-api.cc:375
unusedFunction:t-dll-api.cc:395
//ivl_event_scope()
unusedFunction:t-dll-api.cc:338
unusedFunction:t-dll-api.cc:357
//ivl_expr_bits()
unusedFunction:t-dll-api.cc:382
unusedFunction:t-dll-api.cc:402
//ivl_expr_branch()
unusedFunction:t-dll-api.cc:388
unusedFunction:t-dll-api.cc:409
//ivl_expr_def()
unusedFunction:t-dll-api.cc:394
//ivl_expr_delay_val()
unusedFunction:t-dll-api.cc:410
//ivl_expr_dvalue()
unusedFunction:t-dll-api.cc:416
//ivl_expr_delay_val()
unusedFunction:t-dll-api.cc:432
//ivl_expr_dvalue()
unusedFunction:t-dll-api.cc:439
//ivl_expr_enumtype()
unusedFunction:t-dll-api.cc:422
unusedFunction:t-dll-api.cc:446
//ivl_expr_event()
unusedFunction:t-dll-api.cc:628
unusedFunction:t-dll-api.cc:656
//ivl_expr_file()
unusedFunction:t-dll-api.cc:162
unusedFunction:t-dll-api.cc:178
//ivl_expr_lineno()
unusedFunction:t-dll-api.cc:168
unusedFunction:t-dll-api.cc:184
//ivl_expr_name()
unusedFunction:t-dll-api.cc:433
unusedFunction:t-dll-api.cc:459
//ivl_expr_nature()
unusedFunction:t-dll-api.cc:456
unusedFunction:t-dll-api.cc:483
//ivl_expr_net_type()
unusedFunction:t-dll-api.cc:428
unusedFunction:t-dll-api.cc:453
//ivl_expr_opcode()
unusedFunction:t-dll-api.cc:462
unusedFunction:t-dll-api.cc:490
//ivl_expr_oper1()
unusedFunction:t-dll-api.cc:478
unusedFunction:t-dll-api.cc:506
//ivl_expr_oper2()
unusedFunction:t-dll-api.cc:516
unusedFunction:t-dll-api.cc:544
//ivl_expr_oper3()
unusedFunction:t-dll-api.cc:542
unusedFunction:t-dll-api.cc:570
//ivl_expr_parameter()
unusedFunction:t-dll-api.cc:556
unusedFunction:t-dll-api.cc:584
//ivl_expr_parm()
unusedFunction:t-dll-api.cc:571
unusedFunction:t-dll-api.cc:599
//ivl_expr_parms()
unusedFunction:t-dll-api.cc:598
unusedFunction:t-dll-api.cc:626
//ivl_expr_repeat()
unusedFunction:t-dll-api.cc:621
//ivl_expr_scope()
unusedFunction:t-dll-api.cc:642
//ivl_expr_sel_type()
unusedFunction:t-dll-api.cc:649
//ivl_expr_scope()
unusedFunction:t-dll-api.cc:670
//ivl_expr_sel_type()
unusedFunction:t-dll-api.cc:677
//ivl_expr_signed()
unusedFunction:t-dll-api.cc:674
unusedFunction:t-dll-api.cc:702
//ivl_expr_sized()
unusedFunction:t-dll-api.cc:680
unusedFunction:t-dll-api.cc:708
//ivl_expr_string()
unusedFunction:t-dll-api.cc:686
unusedFunction:t-dll-api.cc:714
//ivl_expr_type()
unusedFunction:t-dll-api.cc:155
unusedFunction:t-dll-api.cc:171
//ivl_expr_uvalue()
unusedFunction:t-dll-api.cc:692
unusedFunction:t-dll-api.cc:721
//ivl_expr_value()
unusedFunction:t-dll-api.cc:717
unusedFunction:t-dll-api.cc:747
//ivl_expr_width()
unusedFunction:t-dll-api.cc:753
unusedFunction:t-dll-api.cc:723
//ivl_file_table_index()
unusedFunction:t-dll-api.cc:765
unusedFunction:t-dll-api.cc:795
//ivl_file_table_item()
unusedFunction:t-dll-api.cc:755
unusedFunction:t-dll-api.cc:785
//ivl_file_table_size()
unusedFunction:t-dll-api.cc:783
unusedFunction:t-dll-api.cc:813
//ivl_island_flag_set()
unusedFunction:t-dll-api.cc:792
unusedFunction:t-dll-api.cc:822
//ivl_island_flag_test()
unusedFunction:t-dll-api.cc:806
unusedFunction:t-dll-api.cc:837
//ivl_logic_attr()
unusedFunction:t-dll-api.cc:832
unusedFunction:t-dll-api.cc:864
//ivl_logic_attr_cnt()
unusedFunction:t-dll-api.cc:848
unusedFunction:t-dll-api.cc:880
//ivl_logic_attr_val()
unusedFunction:t-dll-api.cc:853
unusedFunction:t-dll-api.cc:886
//ivl_logic_basename()
unusedFunction:t-dll-api.cc:901
unusedFunction:t-dll-api.cc:935
//ivl_logic_delay()
unusedFunction:t-dll-api.cc:936
unusedFunction:t-dll-api.cc:974
//ivl_logic_drive0()
unusedFunction:t-dll-api.cc:860
//ivl_logic_drive1()
unusedFunction:t-dll-api.cc:877
//ivl_logic_file()
unusedFunction:t-dll-api.cc:814
//ivl_logic_is_cassign()
unusedFunction:t-dll-api.cc:826
//ivl_logic_lineno()
unusedFunction:t-dll-api.cc:820
//ivl_logic_name()
unusedFunction:t-dll-api.cc:894
//ivl_logic_drive1()
unusedFunction:t-dll-api.cc:911
//ivl_logic_file()
unusedFunction:t-dll-api.cc:846
//ivl_logic_is_cassign()
unusedFunction:t-dll-api.cc:858
//ivl_logic_lineno()
unusedFunction:t-dll-api.cc:852
//ivl_logic_name()
unusedFunction:t-dll-api.cc:928
//ivl_logic_pins()
unusedFunction:t-dll-api.cc:918
unusedFunction:t-dll-api.cc:953
//ivl_logic_scope()
unusedFunction:t-dll-api.cc:907
unusedFunction:t-dll-api.cc:941
//ivl_logic_type()
unusedFunction:t-dll-api.cc:913
unusedFunction:t-dll-api.cc:947
//ivl_logic_udp()
unusedFunction:t-dll-api.cc:929
unusedFunction:t-dll-api.cc:966
//ivl_logic_width()
unusedFunction:t-dll-api.cc:942
unusedFunction:t-dll-api.cc:981
//ivl_lpm_array()
unusedFunction:t-dll-api.cc:1059
unusedFunction:t-dll-api.cc:1109
//ivl_lpm_aset_value()
unusedFunction:t-dll-api.cc:1110
unusedFunction:t-dll-api.cc:1160
//ivl_lpm_async_clr()
unusedFunction:t-dll-api.cc:1005
unusedFunction:t-dll-api.cc:1054
//ivl_lpm_async_set()
unusedFunction:t-dll-api.cc:1035
unusedFunction:t-dll-api.cc:1085
//ivl_lpm_base()
unusedFunction:t-dll-api.cc:1071
//ivl_lpm_basename()
unusedFunction:t-dll-api.cc:1000
//ivl_lpm_clk()
unusedFunction:t-dll-api.cc:1098
//ivl_lpm_data()
unusedFunction:t-dll-api.cc:1167
//ivl_lpm_datab()
unusedFunction:t-dll-api.cc:1264
//ivl_lpm_define()
unusedFunction:t-dll-api.cc:1133
//ivl_lpm_delay()
unusedFunction:t-dll-api.cc:1029
//ivl_lpm_drive0()
unusedFunction:t-dll-api.cc:1393
//ivl_lpm_drive1()
unusedFunction:t-dll-api.cc:1410
//ivl_lpm_enable()
unusedFunction:t-dll-api.cc:1145
//ivl_lpm_file()
unusedFunction:t-dll-api.cc:1157
//ivl_lpm_lineno()
unusedFunction:t-dll-api.cc:1162
//ivl_lpm_name()
unusedFunction:t-dll-api.cc:1298
//ivl_lpm_negedge()
unusedFunction:t-dll-api.cc:1086
//ivl_lpm_select()
unusedFunction:t-dll-api.cc:1433
//ivl_lpm_selects()
unusedFunction:t-dll-api.cc:1449
//ivl_lpm_signed()
unusedFunction:t-dll-api.cc:1466
//ivl_lpm_size()
unusedFunction:t-dll-api.cc:1525
//ivl_lpm_sset_value()
unusedFunction:t-dll-api.cc:1121
//ivl_lpm_basename()
unusedFunction:t-dll-api.cc:1048
//ivl_lpm_clk()
unusedFunction:t-dll-api.cc:1148
//ivl_lpm_data()
unusedFunction:t-dll-api.cc:1221
//ivl_lpm_datab()
unusedFunction:t-dll-api.cc:1321
//ivl_lpm_define()
unusedFunction:t-dll-api.cc:1183
//ivl_lpm_delay()
unusedFunction:t-dll-api.cc:1078
//ivl_lpm_drive0()
unusedFunction:t-dll-api.cc:1453
//ivl_lpm_drive1()
unusedFunction:t-dll-api.cc:1470
//ivl_lpm_enable()
unusedFunction:t-dll-api.cc:1195
//ivl_lpm_file()
unusedFunction:t-dll-api.cc:1209
//ivl_lpm_lineno()
unusedFunction:t-dll-api.cc:1215
//ivl_lpm_name()
unusedFunction:t-dll-api.cc:1355
//ivl_lpm_negedge()
unusedFunction:t-dll-api.cc:1136
//ivl_lpm_select()
unusedFunction:t-dll-api.cc:1493
//ivl_lpm_selects()
unusedFunction:t-dll-api.cc:1510
//ivl_lpm_signed()
unusedFunction:t-dll-api.cc:1528
//ivl_lpm_size()
unusedFunction:t-dll-api.cc:1587
//ivl_lpm_sset_value()
unusedFunction:t-dll-api.cc:1171
//ivl_lpm_string()
unusedFunction:t-dll-api.cc:1577
unusedFunction:t-dll-api.cc:1640
//ivl_lpm_sync_clr()
unusedFunction:t-dll-api.cc:1017
unusedFunction:t-dll-api.cc:1066
//ivl_lpm_sync_set()
unusedFunction:t-dll-api.cc:1047
unusedFunction:t-dll-api.cc:1097
//ivl_lpm_trigger()
unusedFunction:t-dll-api.cc:1594
unusedFunction:t-dll-api.cc:1659
//ivl_lpm_type()
unusedFunction:t-dll-api.cc:1583
unusedFunction:t-dll-api.cc:1647
//ivl_lpm_width()
unusedFunction:t-dll-api.cc:1588
unusedFunction:t-dll-api.cc:1653
//ivl_lval_idx()
unusedFunction:t-dll-api.cc:1616
unusedFunction:t-dll-api.cc:1681
//ivl_lval_mux()
unusedFunction:t-dll-api.cc:1611
unusedFunction:t-dll-api.cc:1676
//ivl_lval_nest()
unusedFunction:t-dll-api.cc:1661
unusedFunction:t-dll-api.cc:1726
//ivl_lval_part_off()
unusedFunction:t-dll-api.cc:1625
unusedFunction:t-dll-api.cc:1690
//ivl_lval_property_idx()
unusedFunction:t-dll-api.cc:1643
unusedFunction:t-dll-api.cc:1708
//ivl_lval_sel_type()
unusedFunction:t-dll-api.cc:1631
unusedFunction:t-dll-api.cc:1696
//ivl_lval_sig()
unusedFunction:t-dll-api.cc:1649
unusedFunction:t-dll-api.cc:1714
//ivl_nature_name()
unusedFunction:t-dll-api.cc:1670
unusedFunction:t-dll-api.cc:1735
//ivl_nexus_get_private()
unusedFunction:t-dll-api.cc:1690
unusedFunction:t-dll-api.cc:1756
//ivl_nexus_name()
unusedFunction:t-dll-api.cc:1679
unusedFunction:t-dll-api.cc:1745
//ivl_nexus_ptr_branch()
unusedFunction:t-dll-api.cc:1733
unusedFunction:t-dll-api.cc:1799
//ivl_nexus_ptr_con()
unusedFunction:t-dll-api.cc:1742
unusedFunction:t-dll-api.cc:1808
//ivl_nexus_ptr_sig()
unusedFunction:t-dll-api.cc:1769
unusedFunction:t-dll-api.cc:1835
//ivl_nexus_ptr_switch()
unusedFunction:t-dll-api.cc:1778
unusedFunction:t-dll-api.cc:1844
//ivl_nexus_set_private()
unusedFunction:t-dll-api.cc:1696
unusedFunction:t-dll-api.cc:1762
//ivl_parameter_basename()
unusedFunction:t-dll-api.cc:1787
unusedFunction:t-dll-api.cc:1853
//ivl_parameter_expr()
unusedFunction:t-dll-api.cc:1830
unusedFunction:t-dll-api.cc:1896
//ivl_parameter_file()
unusedFunction:t-dll-api.cc:1836
unusedFunction:t-dll-api.cc:1902
//ivl_parameter_lineno()
unusedFunction:t-dll-api.cc:1842
unusedFunction:t-dll-api.cc:1908
//ivl_parameter_local()
unusedFunction:t-dll-api.cc:1793
unusedFunction:t-dll-api.cc:1859
//ivl_parameter_lsb()
unusedFunction:t-dll-api.cc:1811
unusedFunction:t-dll-api.cc:1877
//ivl_parameter_msb()
unusedFunction:t-dll-api.cc:1805
unusedFunction:t-dll-api.cc:1871
//ivl_parameter_scope()
unusedFunction:t-dll-api.cc:1848
unusedFunction:t-dll-api.cc:1914
//ivl_parameter_signed()
unusedFunction:t-dll-api.cc:1799
unusedFunction:t-dll-api.cc:1865
//ivl_parameter_width()
unusedFunction:t-dll-api.cc:1821
unusedFunction:t-dll-api.cc:1887
//ivl_path_condit()
unusedFunction:t-dll-api.cc:1854
unusedFunction:t-dll-api.cc:1920
//ivl_path_delay()
unusedFunction:t-dll-api.cc:1866
unusedFunction:t-dll-api.cc:1932
//ivl_path_is_condit()
unusedFunction:t-dll-api.cc:1860
unusedFunction:t-dll-api.cc:1926
//ivl_path_scope()
unusedFunction:t-dll-api.cc:1872
unusedFunction:t-dll-api.cc:1938
//ivl_path_source()
unusedFunction:t-dll-api.cc:1879
unusedFunction:t-dll-api.cc:1945
//ivl_path_source_negedge()
unusedFunction:t-dll-api.cc:1889
unusedFunction:t-dll-api.cc:1957
//ivl_path_source_posedge()
unusedFunction:t-dll-api.cc:1884
unusedFunction:t-dll-api.cc:1951
//ivl_process_analog()
unusedFunction:t-dll-api.cc:1911
unusedFunction:t-dll-api.cc:1981
//ivl_process_attr_cnt()
unusedFunction:t-dll-api.cc:1926
unusedFunction:t-dll-api.cc:1999
//ivl_process_attr_val()
unusedFunction:t-dll-api.cc:1931
unusedFunction:t-dll-api.cc:2005
//ivl_process_file()
unusedFunction:t-dll-api.cc:1894
unusedFunction:t-dll-api.cc:1963
//ivl_process_lineno()
unusedFunction:t-dll-api.cc:1900
unusedFunction:t-dll-api.cc:1969
//ivl_process_scope()
unusedFunction:t-dll-api.cc:1916
unusedFunction:t-dll-api.cc:1987
//ivl_process_stmt()
unusedFunction:t-dll-api.cc:1921
unusedFunction:t-dll-api.cc:1993
//ivl_process_type()
unusedFunction:t-dll-api.cc:1906
unusedFunction:t-dll-api.cc:1975
//ivl_scope_attr_cnt()
unusedFunction:t-dll-api.cc:1938
unusedFunction:t-dll-api.cc:2013
//ivl_scope_attr_val()
unusedFunction:t-dll-api.cc:1944
unusedFunction:t-dll-api.cc:2019
//ivl_scope_basename()
unusedFunction:t-dll-api.cc:1951
//ivl_scope_child()
unusedFunction:t-dll-api.cc:1978
//ivl_scope_children()
unusedFunction:t-dll-api.cc:1958
//ivl_scope_childs()
unusedFunction:t-dll-api.cc:1972
//ivl_scope_class()
unusedFunction:t-dll-api.cc:1984
//ivl_scope_classes()
unusedFunction:t-dll-api.cc:1990
//ivl_scope_def()
unusedFunction:t-dll-api.cc:1996
//ivl_scope_def_file()
unusedFunction:t-dll-api.cc:2002
//ivl_scope_def_lineno()
unusedFunction:t-dll-api.cc:2008
//ivl_scope_enumerate()
unusedFunction:t-dll-api.cc:2020
//ivl_scope_enumerates()
unusedFunction:t-dll-api.cc:2014
//ivl_scope_event()
unusedFunction:t-dll-api.cc:2033
//ivl_scope_events()
unusedFunction:t-dll-api.cc:2027
//ivl_scope_child()
unusedFunction:t-dll-api.cc:2054
//ivl_scope_children()
unusedFunction:t-dll-api.cc:2033
//ivl_scope_childs()
unusedFunction:t-dll-api.cc:2047
//ivl_scope_class()
unusedFunction:t-dll-api.cc:2061
//ivl_scope_classes()
unusedFunction:t-dll-api.cc:2068
//ivl_scope_def()
unusedFunction:t-dll-api.cc:2075
//ivl_scope_def_file()
unusedFunction:t-dll-api.cc:2081
//ivl_scope_def_lineno()
unusedFunction:t-dll-api.cc:2087
//ivl_scope_enumerate()
unusedFunction:t-dll-api.cc:2099
//ivl_scope_enumerates()
unusedFunction:t-dll-api.cc:2093
//ivl_scope_event()
unusedFunction:t-dll-api.cc:2112
//ivl_scope_events()
unusedFunction:t-dll-api.cc:2106
//ivl_scope_file()
unusedFunction:t-dll-api.cc:2040
unusedFunction:t-dll-api.cc:2119
//ivl_scope_func_signed
unusedFunction:t-dll-api.cc:2132
//ivl_scope_func_type
unusedFunction:t-dll-api.cc:2125
//ivl_scope_func_width
unusedFunction:t-dll-api.cc:2140
//ivl_scope_is_auto()
unusedFunction:t-dll-api.cc:2046
unusedFunction:t-dll-api.cc:2148
//ivl_scope_is_cell()
unusedFunction:t-dll-api.cc:2052
unusedFunction:t-dll-api.cc:2154
//ivl_scope_lineno()
unusedFunction:t-dll-api.cc:2058
//ivl_scope_log()
unusedFunction:t-dll-api.cc:2070
//ivl_scope_logs()
unusedFunction:t-dll-api.cc:2064
//ivl_scope_lpm()
unusedFunction:t-dll-api.cc:2083
//ivl_scope_lpms()
unusedFunction:t-dll-api.cc:2077
//ivl_scope_mod_module_port_name()
unusedFunction:t-dll-api.cc:2160
//ivl_scope_log()
unusedFunction:t-dll-api.cc:2172
//ivl_scope_logs()
unusedFunction:t-dll-api.cc:2166
//ivl_scope_lpm()
unusedFunction:t-dll-api.cc:2185
//ivl_scope_lpms()
unusedFunction:t-dll-api.cc:2179
//ivl_scope_mod_module_port_name()
unusedFunction:t-dll-api.cc:2264
//ivl_scope_mod_module_port_type()
unusedFunction:t-dll-api.cc:2169
unusedFunction:t-dll-api.cc:2273
//ivl_scope_mod_module_port_width()
unusedFunction:t-dll-api.cc:2180
unusedFunction:t-dll-api.cc:2285
//ivl_scope_mod_module_ports()
unusedFunction:t-dll-api.cc:2153
unusedFunction:t-dll-api.cc:2257
//ivl_scope_mod_port()
unusedFunction:t-dll-api.cc:2204
unusedFunction:t-dll-api.cc:2310
//ivl_scope_param()
unusedFunction:t-dll-api.cc:2139
unusedFunction:t-dll-api.cc:2243
//ivl_scope_params()
unusedFunction:t-dll-api.cc:2133
unusedFunction:t-dll-api.cc:2237
//ivl_scope_parent()
unusedFunction:t-dll-api.cc:2146
//ivl_scope_port()
unusedFunction:t-dll-api.cc:2195
//ivl_scope_ports()
unusedFunction:t-dll-api.cc:2186
//ivl_scope_sig()
unusedFunction:t-dll-api.cc:2218
//ivl_scope_sigs()
unusedFunction:t-dll-api.cc:2212
//ivl_scope_switch()
unusedFunction:t-dll-api.cc:2231
//ivl_scope_switches()
unusedFunction:t-dll-api.cc:2225
//ivl_scope_time_precision()
unusedFunction:t-dll-api.cc:2238
//ivl_scope_time_units()
unusedFunction:t-dll-api.cc:2244
//ivl_scope_tname()
unusedFunction:t-dll-api.cc:2256
//ivl_scope_type()
unusedFunction:t-dll-api.cc:2250
//ivl_scope_port()
unusedFunction:t-dll-api.cc:2301
//ivl_scope_ports()
unusedFunction:t-dll-api.cc:2292
//ivl_scope_sig()
unusedFunction:t-dll-api.cc:2324
//ivl_scope_sigs()
unusedFunction:t-dll-api.cc:2318
//ivl_scope_switch()
unusedFunction:t-dll-api.cc:2337
//ivl_scope_switches()
unusedFunction:t-dll-api.cc:2331
//ivl_scope_time_precision()
unusedFunction:t-dll-api.cc:2344
//ivl_scope_time_units()
unusedFunction:t-dll-api.cc:2350
//ivl_scope_tname()
unusedFunction:t-dll-api.cc:2362
//ivl_scope_type()
unusedFunction:t-dll-api.cc:2356
//ivl_signal_array_addr_swapped()
unusedFunction:t-dll-api.cc:2272
//ivl_signal_array_base()
unusedFunction:t-dll-api.cc:2262
//ivl_signal_array_count()
unusedFunction:t-dll-api.cc:2267
//ivl_signal_attr()
unusedFunction:t-dll-api.cc:2287
//ivl_signal_attr_cnt()
unusedFunction:t-dll-api.cc:2302
//ivl_signal_attr_val()
unusedFunction:t-dll-api.cc:2307
//ivl_signal_basename()
unusedFunction:t-dll-api.cc:2313
//ivl_signal_data_type()
unusedFunction:t-dll-api.cc:2447
//ivl_signal_dimensions()
unusedFunction:t-dll-api.cc:2277
//ivl_signal_discipline()
unusedFunction:t-dll-api.cc:2282
//ivl_signal_file()
unusedFunction:t-dll-api.cc:2425
//ivl_signal_forced_net()
unusedFunction:t-dll-api.cc:2420
//ivl_signal_integer()
unusedFunction:t-dll-api.cc:2437
//ivl_signal_lineno()
unusedFunction:t-dll-api.cc:2431
//ivl_signal_local()
unusedFunction:t-dll-api.cc:2410
//ivl_signal_lsb()
unusedFunction:t-dll-api.cc:2380
//ivl_signal_array_base()
unusedFunction:t-dll-api.cc:2368
//ivl_signal_array_count()
unusedFunction:t-dll-api.cc:2374
//ivl_signal_attr()
unusedFunction:t-dll-api.cc:2398
//ivl_signal_attr_cnt()
unusedFunction:t-dll-api.cc:2414
//ivl_signal_attr_val()
unusedFunction:t-dll-api.cc:2420
//ivl_signal_basename()
unusedFunction:t-dll-api.cc:2427
//ivl_signal_data_type()
unusedFunction:t-dll-api.cc:2578
//ivl_signal_dimensions()
unusedFunction:t-dll-api.cc:2386
//ivl_signal_discipline()
unusedFunction:t-dll-api.cc:2392
//ivl_signal_file()
unusedFunction:t-dll-api.cc:2555
//ivl_signal_forced_net()
unusedFunction:t-dll-api.cc:2549
//ivl_signal_integer()
unusedFunction:t-dll-api.cc:2567
//ivl_signal_lineno()
unusedFunction:t-dll-api.cc:2561
//ivl_signal_local()
unusedFunction:t-dll-api.cc:2536
//ivl_signal_lsb()
unusedFunction:t-dll-api.cc:2501
//ivl_signal_module_port_index()
unusedFunction:t-dll-api.cc:2405
unusedFunction:t-dll-api.cc:2530
//ivl_signal_msb()
unusedFunction:t-dll-api.cc:2371
unusedFunction:t-dll-api.cc:2491
//ivl_signal_name()
unusedFunction:t-dll-api.cc:2318
unusedFunction:t-dll-api.cc:2433
//ivl_signal_nex()
unusedFunction:t-dll-api.cc:2338
unusedFunction:t-dll-api.cc:2454
//ivl_signal_npath()
unusedFunction:t-dll-api.cc:2457
unusedFunction:t-dll-api.cc:2591
//ivl_signal_packed_dimensions()
unusedFunction:t-dll-api.cc:2354
unusedFunction:t-dll-api.cc:2471
//ivl_signal_packed_lsb()
unusedFunction:t-dll-api.cc:2365
unusedFunction:t-dll-api.cc:2484
//ivl_signal_packed_msb()
unusedFunction:t-dll-api.cc:2359
unusedFunction:t-dll-api.cc:2477
//ivl_signal_path()
unusedFunction:t-dll-api.cc:2462
unusedFunction:t-dll-api.cc:2597
//ivl_signal_port()
unusedFunction:t-dll-api.cc:2400
unusedFunction:t-dll-api.cc:2524
//ivl_signal_scope()
unusedFunction:t-dll-api.cc:2389
unusedFunction:t-dll-api.cc:2511
//ivl_signal_signed()
unusedFunction:t-dll-api.cc:2415
unusedFunction:t-dll-api.cc:2542
//ivl_signal_width()
unusedFunction:t-dll-api.cc:2395
unusedFunction:t-dll-api.cc:2517
//ivl_statement_type()
unusedFunction:t-dll-api.cc:2473
unusedFunction:t-dll-api.cc:2610
//ivl_stmt_block_count()
unusedFunction:t-dll-api.cc:2502
unusedFunction:t-dll-api.cc:2643
//ivl_stmt_block_scope()
unusedFunction:t-dll-api.cc:2488
unusedFunction:t-dll-api.cc:2628
//ivl_stmt_block_stmt()
unusedFunction:t-dll-api.cc:2516
unusedFunction:t-dll-api.cc:2658
//ivl_stmt_call()
unusedFunction:t-dll-api.cc:2531
unusedFunction:t-dll-api.cc:2674
//ivl_stmt_case_count()
unusedFunction:t-dll-api.cc:2551
unusedFunction:t-dll-api.cc:2695
//ivl_stmt_case_expr()
unusedFunction:t-dll-api.cc:2565
unusedFunction:t-dll-api.cc:2710
//ivl_stmt_case_stmt()
unusedFunction:t-dll-api.cc:2581
unusedFunction:t-dll-api.cc:2727
//ivl_stmt_cond_expr()
unusedFunction:t-dll-api.cc:2597
unusedFunction:t-dll-api.cc:2744
//ivl_stmt_cond_false()
unusedFunction:t-dll-api.cc:2623
unusedFunction:t-dll-api.cc:2771
//ivl_stmt_cond_true()
unusedFunction:t-dll-api.cc:2632
unusedFunction:t-dll-api.cc:2781
//ivl_stmt_delay_expr()
unusedFunction:t-dll-api.cc:2641
unusedFunction:t-dll-api.cc:2791
//ivl_stmt_delay_val()
unusedFunction:t-dll-api.cc:2657
unusedFunction:t-dll-api.cc:2808
//ivl_stmt_events()
unusedFunction:t-dll-api.cc:2681
unusedFunction:t-dll-api.cc:2834
//ivl_stmt_file()
unusedFunction:t-dll-api.cc:2478
unusedFunction:t-dll-api.cc:2616
//ivl_stmt_lexp()
unusedFunction:t-dll-api.cc:2708
//ivl_stmt_lineno()
unusedFunction:t-dll-api.cc:2483
//ivl_stmt_lval()
unusedFunction:t-dll-api.cc:2719
//ivl_stmt_lvals()
unusedFunction:t-dll-api.cc:2737
//ivl_stmt_lwidth()
unusedFunction:t-dll-api.cc:2754
//ivl_stmt_name()
unusedFunction:t-dll-api.cc:2786
//ivl_stmt_nevent()
unusedFunction:t-dll-api.cc:2663
//ivl_stmt_opcode()
unusedFunction:t-dll-api.cc:2798
//ivl_stmt_parm()
unusedFunction:t-dll-api.cc:2809
//ivl_stmt_parm_count()
unusedFunction:t-dll-api.cc:2822
//ivl_stmt_rval()
unusedFunction:t-dll-api.cc:2833
//ivl_stmt_sfunc_as_task()
unusedFunction:t-dll-api.cc:2850
//ivl_stmt_sub_stmt()
unusedFunction:t-dll-api.cc:2862
//ivl_stmt_lineno()
unusedFunction:t-dll-api.cc:2622
//ivl_stmt_lval()
unusedFunction:t-dll-api.cc:2874
//ivl_stmt_lvals()
unusedFunction:t-dll-api.cc:2893
//ivl_stmt_lwidth()
unusedFunction:t-dll-api.cc:2911
//ivl_stmt_name()
unusedFunction:t-dll-api.cc:2944
//ivl_stmt_nevent()
unusedFunction:t-dll-api.cc:2815
//ivl_stmt_opcode()
unusedFunction:t-dll-api.cc:2957
//ivl_stmt_parm()
unusedFunction:t-dll-api.cc:2969
//ivl_stmt_parm_count()
unusedFunction:t-dll-api.cc:2983
//ivl_stmt_rval()
unusedFunction:t-dll-api.cc:2995
//ivl_stmt_sfunc_as_task()
unusedFunction:t-dll-api.cc:3013
//ivl_stmt_sub_stmt()
unusedFunction:t-dll-api.cc:3026
//ivl_switch_a()
unusedFunction:t-dll-api.cc:2899
unusedFunction:t-dll-api.cc:3067
//ivl_switch_b()
unusedFunction:t-dll-api.cc:2904
unusedFunction:t-dll-api.cc:3073
//ivl_switch_basename()
unusedFunction:t-dll-api.cc:2884
unusedFunction:t-dll-api.cc:3049
//ivl_switch_delay()
unusedFunction:t-dll-api.cc:2929
unusedFunction:t-dll-api.cc:3103
//ivl_switch_enable()
unusedFunction:t-dll-api.cc:2909
unusedFunction:t-dll-api.cc:3079
//ivl_switch_file()
unusedFunction:t-dll-api.cc:2935
unusedFunction:t-dll-api.cc:3110
//ivl_switch_island()
unusedFunction:t-dll-api.cc:2940
unusedFunction:t-dll-api.cc:3116
//ivl_switch_lineno()
unusedFunction:t-dll-api.cc:2945
unusedFunction:t-dll-api.cc:3122
//ivl_switch_offset()
unusedFunction:t-dll-api.cc:2924
unusedFunction:t-dll-api.cc:3097
//ivl_switch_part()
unusedFunction:t-dll-api.cc:2919
unusedFunction:t-dll-api.cc:3091
//ivl_switch_scope()
unusedFunction:t-dll-api.cc:2889
unusedFunction:t-dll-api.cc:3055
//ivl_switch_type()
unusedFunction:t-dll-api.cc:2894
unusedFunction:t-dll-api.cc:3061
//ivl_switch_width()
unusedFunction:t-dll-api.cc:2914
unusedFunction:t-dll-api.cc:3085
//ivl_type_base()
unusedFunction:t-dll-api.cc:2950
unusedFunction:t-dll-api.cc:3128
//ivl_type_element()
unusedFunction:t-dll-api.cc:2956
unusedFunction:t-dll-api.cc:3134
//ivl_type_name()
unusedFunction:t-dll-api.cc:2985
unusedFunction:t-dll-api.cc:3166
//ivl_type_packed_dimensions()
unusedFunction:t-dll-api.cc:2965
unusedFunction:t-dll-api.cc:3143
//ivl_type_packed_lsb()
unusedFunction:t-dll-api.cc:2971
unusedFunction:t-dll-api.cc:3150
//ivl_type_packed_msb()
unusedFunction:t-dll-api.cc:2978
unusedFunction:t-dll-api.cc:3158
//ivl_type_prop_type()
unusedFunction:t-dll-api.cc:3011
unusedFunction:t-dll-api.cc:3191
//ivl_type_properties()
unusedFunction:t-dll-api.cc:2994
unusedFunction:t-dll-api.cc:3174
//ivl_type_signed()
unusedFunction:t-dll-api.cc:3019
unusedFunction:t-dll-api.cc:3199
//ivl_udp_file()
unusedFunction:t-dll-api.cc:990
unusedFunction:t-dll-api.cc:1036
//ivl_udp_init()
unusedFunction:t-dll-api.cc:958
unusedFunction:t-dll-api.cc:999
//ivl_udp_lineno()
unusedFunction:t-dll-api.cc:995
unusedFunction:t-dll-api.cc:1042
//ivl_udp_name()
unusedFunction:t-dll-api.cc:984
unusedFunction:t-dll-api.cc:1029
//ivl_udp_nin()
unusedFunction:t-dll-api.cc:953
unusedFunction:t-dll-api.cc:993
//ivl_udp_port()
unusedFunction:t-dll-api.cc:963
unusedFunction:t-dll-api.cc:1005
//ivl_udp_row()
unusedFunction:t-dll-api.cc:971
unusedFunction:t-dll-api.cc:1014
//ivl_udp_rows()
unusedFunction:t-dll-api.cc:979
unusedFunction:t-dll-api.cc:1023
// ivl_udp_sequ()
unusedFunction:t-dll-api.cc:948
unusedFunction:t-dll-api.cc:987

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2016 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-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
@ -187,9 +187,15 @@ ostream& operator << (ostream&fd, NetCaseCmp::kind_t that)
case NetCaseCmp::NEQ:
fd << "!==";
break;
case NetCaseCmp::XEQ:
case NetCaseCmp::WEQ:
fd << "==?";
break;
case NetCaseCmp::WNE:
fd << "!=?";
break;
case NetCaseCmp::XEQ:
fd << "==x?";
break;
case NetCaseCmp::ZEQ:
fd << "==z?";
break;
@ -984,6 +990,18 @@ void NetProcTop::dump(ostream&o, unsigned ind) const
o << "always /* " << get_fileline() << " in "
<< scope_path(scope_) << " */" << endl;
break;
case IVL_PR_ALWAYS_COMB:
o << "always_comb /* " << get_fileline() << " in "
<< scope_path(scope_) << " */" << endl;
break;
case IVL_PR_ALWAYS_FF:
o << "always_ff /* " << get_fileline() << " in "
<< scope_path(scope_) << " */" << endl;
break;
case IVL_PR_ALWAYS_LATCH:
o << "always_latch /* " << get_fileline() << " in "
<< scope_path(scope_) << " */" << endl;
break;
case IVL_PR_FINAL:
o << "final /* " << get_fileline() << " in "
<< scope_path(scope_) << " */" << endl;
@ -1011,6 +1029,13 @@ void NetAnalogTop::dump(ostream&o, unsigned ind) const
<< scope_path(scope_) << " */" << endl;
break;
// These are not used in an analog context.
case IVL_PR_ALWAYS_COMB:
case IVL_PR_ALWAYS_FF:
case IVL_PR_ALWAYS_LATCH:
assert(0);
break;
case IVL_PR_FINAL:
o << "analog final /* " << get_fileline() << " in "
<< scope_path(scope_) << " */" << endl;
@ -1390,6 +1415,8 @@ void NetScope::dump(ostream&o) const
if (is_interface()) o << " (interface)";
o << " " << children_.size() << " children, "
<< classes_.size() << " classes" << endl;
if (unit() && !is_unit())
o << " in compilation unit " << unit()->basename() << endl;
for (unsigned idx = 0 ; idx < attr_cnt() ; idx += 1)
o << " (* " << attr_key(idx) << " = "
@ -1629,11 +1656,14 @@ void NetEBinary::dump(ostream&o) const
case 'A':
o << "~&";
break;
case 'e':
o << "==";
break;
case 'E':
o << "===";
break;
case 'e':
o << "==";
case 'w':
o << "==?";
break;
case 'G':
o << ">=";
@ -1650,6 +1680,9 @@ void NetEBinary::dump(ostream&o) const
case 'N':
o << "!==";
break;
case 'W':
o << "!=?";
break;
case 'o':
o << "||";
break;
@ -1902,18 +1935,6 @@ void Design::dump(ostream&o) const
cur->second->dump(o);
}
o << "$ROOT CLASSES:" << endl;
for (map<perm_string,netclass_t*>::const_iterator cur = classes_.begin()
; cur != classes_.end() ; ++cur) {
cur->second->dump_scope(o);
}
o << "$ROOT TASKS/FUNCTIONS:" << endl;
for (map<NetScope*,PTaskFunc*>::const_iterator cur = root_tasks_.begin()
; cur != root_tasks_.end() ; ++ cur) {
cur->first->dump(o);
}
o << "SCOPES:" << endl;
for (list<NetScope*>::const_iterator scope = root_scopes_.begin();
scope != root_scopes_.end(); ++ scope ) {

View File

@ -4,7 +4,7 @@
%{
/*
* Copyright (c) 2001-2016 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-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
@ -252,7 +252,7 @@ void destroy_lexor(void)
{
# ifdef FLEX_SCANNER
# if YY_FLEX_MAJOR_VERSION >= 2 && YY_FLEX_MINOR_VERSION >= 5
# if defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9
# if YY_FLEX_MINOR_VERSION > 5 || defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9
yylex_destroy();
# endif
# endif

View File

@ -1,10 +1,10 @@
.TH iverilog 1 "Oct 2nd, 2016" "" "Version %M.%n%E"
.TH iverilog 1 "Nov 8th, 2017" "" "Version %M.%n%E"
.SH NAME
iverilog - Icarus Verilog compiler
.SH SYNOPSIS
.B iverilog
[\-ESVv] [\-Bpath] [\-ccmdfile|\-fcmdfile] [\-Dmacro[=defn]]
[\-ESuVv] [\-Bpath] [\-ccmdfile|\-fcmdfile] [\-Dmacro[=defn]]
[\-Pparameter=value] [\-pflag=value] [\-dname]
[\-g1995\:|\-g2001\:|\-g2005\:|\-g2005-sv\:|\-g2009\:|\-g2012\:|\-g<feature>]
[\-Iincludedir] [\-mmodule] [\-M[mode=]file] [\-Nfile] [\-ooutputfilename]
@ -222,6 +222,12 @@ will suppress the warning that the compiler is making a choice.
Use this switch to specify the target output format. See the
\fBTARGETS\fP section below for a list of valid output formats.
.TP 8
.B -u
Treat each source file as a separate compilation unit (as defined in
SystemVerilog). If compiling for an \fIIEEE1364\fP generation, this
will just reset all compiler directives (including macro definitions)
before each new file is processed.
.TP 8
.B -v
Turn on verbose messages. This will print the command lines that are
executed to perform the actual compilation, along with version
@ -264,7 +270,7 @@ that contain Verilog source files. During elaboration, the compiler
notices the instantiation of undefined module types. If the user
specifies library search directories, the compiler will search the
directory for files with the name of the missing module type. If it
finds such a file, it loads it as a Verilog source file, they tries
finds such a file, it loads it as a Verilog source file, then tries
again to elaborate the module.
Library module files should contain only a single module, but this is
@ -310,8 +316,9 @@ after a \fB\-Wall\fP argument to suppress isolated warning types.
.TP 8
.B all
This enables the anachronisms, implicit, portbind, select\-range,
timescale, and sensitivity\-entire\-array warning categories.
This enables the anachronisms, implicit, macro-replacement, portbind,
select\-range, timescale, and sensitivity\-entire\-array warning
categories.
.TP 8
.B anachronisms
@ -324,6 +331,13 @@ This enables warnings for creation of implicit declarations. For
example, if a scalar wire X is used but not declared in the Verilog
source, this will print a warning at its first use.
.TP 8
.B macro-redefinition\fI | \fPmacro-replacement
This enables preprocessor warnings when a macro is being redefined.
The first variant prints a warning any time a macro is redefined.
The second variant only prints a warning if the macro text changes.
Use \fBno-macro-redefinition\fP to turn off all warnings of this type.
.TP 8
.B portbind
This enables warnings for ports of module instantiations that are not
@ -564,7 +578,7 @@ Tips on using, debugging, and developing the compiler can be found at
.SH COPYRIGHT
.nf
Copyright \(co 2002\-2016 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

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2016 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
@ -38,7 +38,7 @@ const char NOTICE[] =
;
const char HELP[] =
"Usage: iverilog [-ESvV] [-B base] [-c cmdfile|-f cmdfile]\n"
"Usage: iverilog [-EiSuvV] [-B base] [-c cmdfile|-f cmdfile]\n"
" [-g1995|-g2001|-g2005|-g2005-sv|-g2009|-g2012] [-g<feature>]\n"
" [-D macro[=defn]] [-I includedir]\n"
" [-M [mode=]depfile] [-m module]\n"
@ -138,7 +138,12 @@ int gen_std_include = 1;
of the include list. */
int gen_relative_include = 0;
char warning_flags[16] = "n";
char warning_flags[17] = "n";
int separate_compilation_flag = 0;
/* Boolean: true means ignore errors about missing modules */
int ignore_missing_modules = 0;
unsigned integer_width = 32;
@ -341,10 +346,15 @@ static int t_version_only(void)
static void build_preprocess_command(int e_flag)
{
snprintf(tmp, sizeof tmp, "%s%civlpp %s%s -F\"%s\" -f\"%s\" -p\"%s\" ",
ivlpp_dir, sep, verbose_flag?" -v":"",
e_flag?"":" -L", defines_path, source_path,
compiled_defines_path);
snprintf(tmp, sizeof tmp, "%s%civlpp %s%s%s -F\"%s\" -f\"%s\" -p\"%s\"%s",
ivlpp_dir, sep,
verbose_flag ? " -v" : "",
e_flag ? "" : " -L",
strchr(warning_flags, 'r') ? " -Wredef-all " :
strchr(warning_flags, 'R') ? " -Wredef-chg " : "",
defines_path, source_path,
compiled_defines_path,
e_flag ? "" : " | ");
}
static int t_preprocess_only(void)
@ -407,8 +417,12 @@ static int t_compile(void)
{
unsigned rc;
/* Start by building the preprocess command line. */
build_preprocess_command(0);
/* Start by building the preprocess command line, if required.
This pipes into the main ivl command. */
if (!separate_compilation_flag)
build_preprocess_command(0);
else
strcpy(tmp, "");
size_t ncmd = strlen(tmp);
char*cmd = malloc(ncmd + 1);
@ -418,8 +432,8 @@ static int t_compile(void)
int rtn;
#endif
/* Build the ivl command and pipe it to the preprocessor. */
snprintf(tmp, sizeof tmp, " | %s%civl", base, sep);
/* Build the ivl command. */
snprintf(tmp, sizeof tmp, "%s%civl", base, sep);
rc = strlen(tmp);
cmd = realloc(cmd, ncmd+rc+1);
strcpy(cmd+ncmd, tmp);
@ -447,7 +461,16 @@ static int t_compile(void)
strcpy(cmd+ncmd, tmp);
ncmd += rc;
snprintf(tmp, sizeof tmp, " -C\"%s\" -- -", iconfig_common_path);
snprintf(tmp, sizeof tmp, " -C\"%s\"", iconfig_common_path);
rc = strlen(tmp);
cmd = realloc(cmd, ncmd+rc+1);
strcpy(cmd+ncmd, tmp);
ncmd += rc;
if (separate_compilation_flag)
snprintf(tmp, sizeof tmp, " -F\"%s\"", source_path);
else
snprintf(tmp, sizeof tmp, " -- -");
rc = strlen(tmp);
cmd = realloc(cmd, ncmd+rc+1);
strcpy(cmd+ncmd, tmp);
@ -498,6 +521,7 @@ static void process_warning_switch(const char*name)
process_warning_switch("anachronisms");
process_warning_switch("implicit");
process_warning_switch("implicit-dimensions");
process_warning_switch("macro-replacement");
process_warning_switch("portbind");
process_warning_switch("select-range");
process_warning_switch("timescale");
@ -514,6 +538,12 @@ static void process_warning_switch(const char*name)
} else if (strcmp(name,"implicit-dimensions") == 0) {
if (! strchr(warning_flags, 'd'))
strcat(warning_flags, "d");
} else if (strcmp(name,"macro-redefinition") == 0) {
if (! strchr(warning_flags, 'r'))
strcat(warning_flags, "r");
} else if (strcmp(name,"macro-replacement") == 0) {
if (! strchr(warning_flags, 'R'))
strcat(warning_flags, "R");
} else if (strcmp(name,"portbind") == 0) {
if (! strchr(warning_flags, 'p'))
strcat(warning_flags, "p");
@ -558,6 +588,17 @@ static void process_warning_switch(const char*name)
cp[0] = cp[1];
cp += 1;
}
} else if (strcmp(name,"no-macro-redefinition") == 0) {
char*cp = strchr(warning_flags, 'r');
if (cp) while (*cp) {
cp[0] = cp[1];
cp += 1;
}
cp = strchr(warning_flags, 'R');
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) {
@ -987,7 +1028,7 @@ int main(int argc, char **argv)
}
}
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) {
while ((opt = getopt(argc, argv, "B:c:D:d:Ef:g:hl:I:iM:m:N:o:P:p:Ss:T:t:uvVW:y:Y:")) != EOF) {
switch (opt) {
case 'B':
@ -1042,6 +1083,10 @@ int main(int argc, char **argv)
process_include_dir(optarg);
break;
case 'i':
ignore_missing_modules = 1;
break;
case 'l':
process_file_name(optarg, 1);
break;
@ -1086,6 +1131,9 @@ int main(int argc, char **argv)
case 't':
targ = optarg;
break;
case 'u':
separate_compilation_flag = 1;
break;
case 'v':
verbose_flag = 1;
break;
@ -1128,7 +1176,7 @@ int main(int argc, char **argv)
if (version_flag || verbose_flag) {
printf("Icarus Verilog version " VERSION " (" VERSION_TAG ")\n\n");
printf("Copyright 1998-2015 Stephen Williams\n\n");
printf("Copyright 1998-2017 Stephen Williams\n\n");
puts(NOTICE);
}
@ -1184,6 +1232,7 @@ int main(int argc, char **argv)
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);
fprintf(iconfig_file, "ignore_missing_modules:%s\n", ignore_missing_modules ? "true" : "false");
fprintf(iconfig_file, "out:%s\n", opath);
if (depfile) {
fprintf(iconfig_file, "depfile:%s\n", depfile);
@ -1260,8 +1309,12 @@ int main(int argc, char **argv)
will append to the file, so this is necessary to make sure
it starts out empty. */
if (depfile) {
FILE*fd = fopen(depfile, "w");
fclose(fd);
FILE *fd = fopen(depfile, "w");
if (!fd) {
fprintf(stderr, "%s: can't open %s file.\n\n%s\n", argv[0], depfile, HELP);
return 1;
}
fclose(fd);
}
if (source_count == 0 && !version_flag) {
@ -1276,8 +1329,12 @@ int main(int argc, char **argv)
/* Write the preprocessor command needed to preprocess a
single file. This may be used to preprocess library
files. */
fprintf(iconfig_file, "ivlpp:%s%civlpp -L -F\"%s\" -P\"%s\"\n",
ivlpp_dir, sep, defines_path, compiled_defines_path);
fprintf(iconfig_file, "ivlpp:%s%civlpp %s -L -F\"%s\" -P\"%s\"\n",
ivlpp_dir, sep,
strchr(warning_flags, 'r') ? "-Wredef-all" :
strchr(warning_flags, 'R') ? "-Wredef-chg" : "",
defines_path, compiled_defines_path
);
/* Done writing to the iconfig file. Close it now. */
fclose(iconfig_file);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2016 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2018 Stephen Williams (steve@icarus.com)
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
@ -329,10 +329,12 @@ unsigned PEBinary::test_width(Design*des, NetScope*scope, width_mode_t&mode)
case '>': // > Should be handled by PEBComp
case 'e': // == Should be handled by PEBComp
case 'E': // === Should be handled by PEBComp
case 'w': // ==? Should be handled by PEBComp
case 'L': // <= Should be handled by PEBComp
case 'G': // >= Should be handled by PEBComp
case 'n': // != Should be handled by PEBComp
case 'N': // !== Should be handled by PEBComp
case 'W': // !=? Should be handled by PEBComp
case 'p': // ** should be handled by PEBPower
ivl_assert(*this, 0);
default:
@ -668,6 +670,18 @@ NetExpr* PEBComp::elaborate_expr(Design*des, NetScope*scope,
return 0;
}
break;
case 'w': /* ==? */
case 'W': /* !=? */
if ((lp->expr_type() != IVL_VT_BOOL && lp->expr_type() != IVL_VT_LOGIC) ||
(rp->expr_type() != IVL_VT_BOOL && rp->expr_type() != IVL_VT_LOGIC)) {
cerr << get_fileline() << ": error: "
<< human_readable_op(op_)
<< " operator may only have INTEGRAL operands."
<< endl;
des->errors += 1;
return 0;
}
break;
default:
break;
}
@ -1442,6 +1456,13 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope,
return 0;
}
if (!type_is_vectorable(expr_type_)) {
cerr << get_fileline() << ": error: The argument to "
<< name << " must be a vector type." << endl;
des->errors += 1;
return 0;
}
if (debug_elaborate) {
cerr << get_fileline() << ": PECallFunction::elaborate_sfunc_: "
<< name << " expression is the argument cast to expr_wid=" << expr_wid << endl;
@ -2264,8 +2285,8 @@ NetExpr* PECallFunction::elaborate_base_(Design*des, NetScope*scope, NetScope*ds
}
cerr << get_fileline() << ": internal error: Unable to locate "
"function return value for " << path_
<< " in " << dscope->basename() << "." << endl;
"function return value for " << path_
<< " in " << dscope->basename() << "." << endl;
des->errors += 1;
return 0;
}
@ -2536,7 +2557,13 @@ NetExpr* PECastSize::elaborate_expr(Design*des, NetScope*scope,
ivl_assert(*this, size_);
ivl_assert(*this, base_);
NetExpr*sub = base_->elaborate_expr(des, scope, base_->expr_width(), flags);
// When changing size, a cast behaves exactly like an assignment,
// so the result size affects the final expression width.
unsigned cast_width = base_->expr_width();
if (cast_width < expr_width_)
cast_width = expr_width_;
NetExpr*sub = base_->elaborate_expr(des, scope, cast_width, flags);
// Perform the cast. The extension method (zero/sign), if needed,
// depends on the type of the base expression.
@ -2590,7 +2617,7 @@ NetExpr* PECastType::elaborate_expr(Design*des, NetScope*scope,
// Find rounded up length that can fit the whole casted array of vectors
int len = base->expr_width() + vector->packed_width() - 1;
if(base->expr_width() > vector->packed_width()) {
if(base->expr_width() > (unsigned)vector->packed_width()) {
len /= vector->packed_width();
} else {
len /= base->expr_width();
@ -2754,6 +2781,7 @@ NetExpr* PEConcat::elaborate_expr(Design*, NetScope*,
tmp->set_line(*this);
return tmp;
}
// fallthrough
default:
cerr << get_fileline() << ": internal error: "
<< "I don't know how to elaborate(ivl_type_t)"
@ -3141,6 +3169,25 @@ unsigned PEIdent::test_width_method_(Design*des, NetScope*scope, width_mode_t&)
}
}
// Look for the enumeration attributes.
if (const netenum_t*netenum = net->enumeration()) {
if (member_name == "num") {
expr_type_ = IVL_VT_BOOL;
expr_width_ = 32;
min_width_ = 32;
signed_flag_= true;
return 32;
}
if ((member_name == "first") || (member_name == "last") ||
(member_name == "next") || (member_name == "prev")) {
expr_type_ = netenum->base_type();
expr_width_ = netenum->packed_width();;
min_width_ = expr_width_;
signed_flag_ = netenum->get_signed();
return expr_width_;
}
}
return 0;
}
@ -3448,29 +3495,41 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
}
if (net == 0) {
cerr << get_fileline() << ": internal error: "
<< "Expecting idents with ntype to be signals." << endl;
cerr << get_fileline() << ": error: Unable to bind variable `"
<< path_ << "' in `" << scope_path(use_scope) << "'" << endl;
des->errors += 1;
return 0;
}
if (! ntype->type_compatible(net->net_type())) {
cerr << get_fileline() << ": internal_error: "
<< "net type doesn't match context type." << endl;
if (const netdarray_t*array_type = dynamic_cast<const netdarray_t*> (ntype)) {
if (array_type->type_compatible(net->net_type())) {
NetESignal*tmp = new NetESignal(net);
tmp->set_line(*this);
return tmp;
}
cerr << get_fileline() << ": : "
<< "net type=";
// Icarus allows a dynamic array to be initialised with a
// single elementary value, so try that next.
ntype = array_type->element_type();
}
if (! ntype->type_compatible(net->net_type())) {
cerr << get_fileline() << ": error: the type of the variable '"
<< path_ << "' doesn't match the context type." << endl;
cerr << get_fileline() << ": : " << "variable type=";
if (net->net_type())
net->net_type()->debug_dump(cerr);
else
cerr << "<nil>";
cerr << endl;
cerr << get_fileline() << ": : "
<< "context type=";
cerr << get_fileline() << ": : " << "context type=";
ivl_assert(*this, ntype);
ntype->debug_dump(cerr);
cerr << endl;
des->errors += 1;
return 0;
}
ivl_assert(*this, ntype->type_compatible(net->net_type()));
@ -5326,9 +5385,8 @@ NetExpr* PENewArray::elaborate_expr(Design*des, NetScope*scope,
// expression. Elaborate the expression as an element
// type. The run-time will assign this value to each element.
const netarray_t*array_type = dynamic_cast<const netarray_t*> (ntype);
ivl_type_t elem_type = array_type->element_type();
init_val = init_->elaborate_expr(des, scope, elem_type, flags);
init_val = init_->elaborate_expr(des, scope, array_type, flags);
}
NetENew*tmp = new NetENew(ntype, size, init_val);
@ -5579,6 +5637,10 @@ unsigned PENumber::test_width(Design*, NetScope*, width_mode_t&mode)
NetExpr* PENumber::elaborate_expr(Design*des, NetScope*, ivl_type_t ntype, unsigned) const
{
// Icarus allows dynamic arrays to be initialised with a single value.
if (const netdarray_t*array_type = dynamic_cast<const netdarray_t*> (ntype))
ntype = array_type->element_type();
const netvector_t*use_type = dynamic_cast<const netvector_t*> (ntype);
if (use_type == 0) {
cerr << get_fileline() << ": internal error: "
@ -5685,7 +5747,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) {

View File

@ -1194,7 +1194,12 @@ bool PEIdent::elaborate_lval_net_packed_member_(Design*des, NetScope*scope,
if (!name_tail.index.empty())
use_sel = name_tail.index.back().sel;
ivl_assert(*this, use_sel == index_component_t::SEL_NONE || use_sel == index_component_t::SEL_BIT);
if (use_sel != index_component_t::SEL_NONE && use_sel != index_component_t::SEL_BIT) {
cerr << get_fileline() << ": sorry: Assignments to part selects of "
"a struct member are not yet supported." << endl;
des->errors += 1;
return false;
}
if (! name_tail.index.empty()) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2016 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2017 Stephen Williams (steve@icarus.com)
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
@ -59,7 +59,7 @@ 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);
scope->time_from_timescale(pscope->has_explicit_timescale());
des->set_precision(pscope->time_precision);
}
@ -167,8 +167,7 @@ static void collect_scope_specparams_(Design*des, NetScope*scope,
}
/*
* Elaborate the enumeration into the given scope. If scope==0, then
* the enumeration goes into $root instead of a scope.
* Elaborate the enumeration into the given scope.
*/
static void elaborate_scope_enumeration(Design*des, NetScope*scope,
enum_type_t*enum_type)
@ -193,10 +192,7 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
enum_type);
use_enum->set_line(enum_type->li);
if (scope)
scope->add_enumeration_set(enum_type, use_enum);
else
des->add_enumeration_set(enum_type, use_enum);
scope->add_enumeration_set(enum_type, use_enum);
size_t name_idx = 0;
// Find the enumeration width.
@ -364,10 +360,7 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
}
rc_flag = use_enum->insert_name(name_idx, cur->name, cur_value);
if (scope)
rc_flag &= scope->add_enumeration_name(use_enum, cur->name);
else
rc_flag &= des->add_enumeration_name(use_enum, cur->name);
rc_flag &= scope->add_enumeration_name(use_enum, cur->name);
if (! rc_flag) {
cerr << use_enum->get_fileline()
@ -397,15 +390,6 @@ static void elaborate_scope_enumerations(Design*des, NetScope*scope,
}
}
void elaborate_rootscope_enumerations(Design*des)
{
for (set<enum_type_t*>::const_iterator cur = pform_enum_sets.begin()
; cur != pform_enum_sets.end() ; ++ cur) {
enum_type_t*curp = *cur;
elaborate_scope_enumeration(des, 0, curp);
}
}
/*
* If the pclass includes an implicit and explicit constructor, then
* merge the implicit constructor into the explicit constructor as
@ -509,7 +493,6 @@ static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass)
netclass_t*use_base_class = 0;
if (base_class) {
ivl_assert(*pclass, scope);
use_base_class = scope->find_class(base_class->name);
if (use_base_class == 0) {
cerr << pclass->get_fileline() << ": error: "
@ -525,9 +508,10 @@ static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass)
use_type->save_elaborated_type = use_class;
// Class scopes have no parent scope, because references are
// not allowed to escape a class method.
// not allowed to escape a class method. But they are allowed
// to reference the compilation unit scope.
NetScope*class_scope = new NetScope(0, hname_t(pclass->pscope_name()),
NetScope::CLASS);
NetScope::CLASS, scope->unit());
class_scope->set_line(pclass);
class_scope->set_class_def(use_class);
use_class->set_class_scope(class_scope);
@ -586,12 +570,7 @@ static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass)
cur->second->elaborate_scope(des, method_scope);
}
if (scope) {
scope->add_class(use_class);
} else {
des->add_class(use_class, pclass);
}
scope->add_class(use_class);
}
static void elaborate_scope_classes(Design*des, NetScope*scope,
@ -603,18 +582,6 @@ static void elaborate_scope_classes(Design*des, NetScope*scope,
}
}
void elaborate_rootscope_classes(Design*des)
{
if (pform_classes.empty())
return;
for (map<perm_string,PClass*>::iterator cur = pform_classes.begin()
; cur != pform_classes.end() ; ++ cur) {
blend_class_constructors(cur->second);
elaborate_scope_class(des, 0, cur->second);
}
}
static void replace_scope_parameters_(NetScope*scope, const LineInfo&loc,
const Module::replace_t&replacements)
{
@ -664,11 +631,6 @@ 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) {
set_scope_timescale(des, task_scope, task);
des->add_root_task(task_scope, task);
}
if (debug_scopes) {
cerr << task->get_fileline() << ": elaborate_scope_task: "
<< "Elaborate task scope " << scope_path(task_scope) << endl;
@ -731,11 +693,6 @@ 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) {
set_scope_timescale(des, task_scope, task);
des->add_root_task(task_scope, task);
}
if (debug_scopes) {
cerr << task->get_fileline() << ": elaborate_scope_func: "
<< "Elaborate task scope " << scope_path(task_scope) << endl;
@ -791,28 +748,6 @@ static void elaborate_scope_funcs(Design*des, NetScope*scope,
}
void elaborate_rootscope_tasks(Design*des)
{
for (map<perm_string,PTaskFunc*>::iterator cur = pform_tasks.begin()
; cur != pform_tasks.end() ; ++ cur) {
if (PTask*task = dynamic_cast<PTask*> (cur->second)) {
elaborate_scope_task(des, 0, task);
continue;
}
if (PFunction*func = dynamic_cast<PFunction*>(cur->second)) {
elaborate_scope_func(des, 0, func);
continue;
}
cerr << cur->second->get_fileline() << ": internal error: "
<< "elaborate_rootscope_tasks does not understand "
<< "this object," << endl;
des->errors += 1;
}
}
class generate_schemes_work_item_t : public elaborator_work_item_t {
public:
generate_schemes_work_item_t(Design*des__, NetScope*scope, Module*mod)
@ -1169,7 +1104,7 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
container->genvar_tmp_val = genvar;
delete step;
delete test_ex;
test_ex = elab_and_eval(des, container, loop_test, -1);
test_ex = elab_and_eval(des, container, loop_test, -1, true);
test = dynamic_cast<NetEConst*>(test_ex);
assert(test);
}
@ -1728,6 +1663,10 @@ void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*s
<< "." << endl;
}
struct attrib_list_t*attrib_list;
unsigned attrib_list_n = 0;
attrib_list = evaluate_attributes(attributes, attrib_list_n, des, sc);
// Run through the module instances, and make scopes out of
// them. Also do parameter overrides that are done on the
// instantiation line.
@ -1754,7 +1693,7 @@ void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*s
// Create the new scope as a MODULE with my name. Note
// that if this is a nested module, mark it thus so that
// scope searches will continue into the parent scope.
NetScope*my_scope = new NetScope(sc, use_name, NetScope::MODULE,
NetScope*my_scope = new NetScope(sc, use_name, NetScope::MODULE, 0,
bound_type_? true : false,
mod->program_block,
mod->is_interface);
@ -1762,6 +1701,9 @@ void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*s
get_lineno(), mod->get_lineno());
my_scope->set_module_name(mod->mod_name());
for (unsigned adx = 0 ; adx < attrib_list_n ; adx += 1)
my_scope->attribute(attrib_list[adx].key, attrib_list[adx].val);
instances[idx] = my_scope;
set_scope_timescale(des, my_scope, mod);
@ -1820,6 +1762,7 @@ void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*s
mod->elaborate_scope(des, my_scope, replace);
}
delete[]attrib_list;
/* Stash the instance array of scopes into the parent
scope. Later elaboration passes will use this vector to

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2016 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2017 Stephen Williams (steve@icarus.com)
* Copyright CERN 2012 / Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
@ -1333,27 +1333,3 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
return sig;
}
void Design::root_elaborate_sig(void)
{
for (map<perm_string,netclass_t*>::const_iterator cur = classes_.begin()
; cur != classes_.end() ; ++ cur) {
netclass_t*cur_class = cur->second;
PClass*cur_pclass = class_to_pclass_[cur_class];
cur_class->elaborate_sig(this, cur_pclass);
}
for (map<NetScope*,PTaskFunc*>::iterator cur = root_tasks_.begin()
; cur != root_tasks_.end() ; ++ cur) {
if (debug_elaborate) {
cerr << cur->second->get_fileline() << ": root_elaborate_sig: "
<< "Elaborate_sig for root task/func " << scope_path(cur->first) << endl;
}
cur->second->elaborate_sig(this, cur->first);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2016 Stephen Williams (steve@icarus.com)
* Copyright (c) 2012-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
@ -78,9 +78,8 @@ static void elaborate_array_ranges(Design*des, NetScope*scope,
*/
ivl_type_s* data_type_t::elaborate_type(Design*des, NetScope*scope)
{
ivl_assert(*this, scope);
Definitions*use_definitions = scope;
if (use_definitions == 0)
use_definitions = des;
map<Definitions*,ivl_type_s*>::iterator pos = cache_type_elaborate_.lower_bound(use_definitions);
if (pos != cache_type_elaborate_.end() && pos->first == use_definitions)
@ -147,13 +146,13 @@ ivl_type_s* class_type_t::elaborate_type_raw(Design*, NetScope*) const
* available at the right time. At that time, the netenum_t* object is
* stashed in the scope so that I can retrieve it here.
*/
ivl_type_s* enum_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
ivl_type_s* enum_type_t::elaborate_type_raw(Design*, NetScope*scope) const
{
ivl_assert(*this, scope);
ivl_type_s*tmp = scope->enumeration_for_key(this);
if (tmp) return tmp;
tmp = des->enumeration_for_key(this);
if (tmp == 0 && scope->unit()) {
tmp = scope->unit()->enumeration_for_key(this);
}
return tmp;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2016 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-2018 Stephen Williams (steve@icarus.com)
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
@ -2204,8 +2204,10 @@ void PGModule::elaborate(Design*des, NetScope*scope) const
return;
}
cerr << get_fileline() << ": internal error: Unknown module type: " <<
type_ << endl;
if (!ignore_missing_modules) {
cerr << get_fileline() << ": internal error: Unknown module type: " <<
type_ << endl;
}
}
void PGModule::elaborate_scope(Design*des, NetScope*sc) const
@ -2249,9 +2251,11 @@ void PGModule::elaborate_scope(Design*des, NetScope*sc) const
// Not a module or primitive that I know about or can find by
// any means, so give up.
cerr << get_fileline() << ": error: Unknown module type: " << type_ << endl;
missing_modules[type_] += 1;
des->errors += 1;
if (!ignore_missing_modules) {
cerr << get_fileline() << ": error: Unknown module type: " << type_ << endl;
missing_modules[type_] += 1;
des->errors += 1;
}
}
@ -2351,19 +2355,7 @@ static NetExpr*elaborate_delay_expr(PExpr*expr, Design*des, NetScope*scope)
{
NetExpr*dex = elab_and_eval(des, scope, expr, -1);
/* Print a warning if we find default and `timescale based
* delays in the design, since this is likely an error. */
if (scope->time_from_timescale()) dly_used_timescale = true;
else dly_used_no_timescale = true;
if (display_ts_dly_warning &&
dly_used_no_timescale && dly_used_timescale) {
cerr << "warning: Found both default and "
"`timescale based delays. Use" << endl;
cerr << " -Wtimescale to find the "
"module(s) with no `timescale." << endl;
display_ts_dly_warning = false;
}
check_for_inconsistent_delays(scope);
/* If the delay expression is a real constant or vector
constant, then evaluate it, scale it to the local time
@ -2914,11 +2906,12 @@ NetProc* PBlock::elaborate(Design*des, NetScope*scope) const
if (nscope == 0)
nscope = scope;
// Handle the special case that the block contains only one
// statement. There is no need to keep the block node. Also,
// don't elide named blocks, because they might be referenced
// elsewhere.
if ((list_.size() == 1) && (pscope_name() == 0)) {
// Handle the special case that the sequential block contains
// only one statement. There is no need to keep the block node.
// Also, don't elide named blocks, because they might be
// referenced elsewhere.
if ((type == NetBlock::SEQU) && (list_.size() == 1) &&
(pscope_name() == 0)) {
assert(list_[0]);
NetProc*tmp = list_[0]->elaborate(des, nscope);
return tmp;
@ -4198,6 +4191,7 @@ NetProc* PEventStatement::elaborate_st(Design*des, NetScope*scope,
NetEvent*ev = new NetEvent(scope->local_symbol());
ev->set_line(*this);
ev->local_flag(true);
unsigned expr_count = 0;
NetEvWait*wa = new NetEvWait(enet);
@ -4208,14 +4202,18 @@ NetProc* PEventStatement::elaborate_st(Design*des, NetScope*scope,
if (expr_.count() == 0) {
assert(enet);
/* For synthesis we want just the inputs, but for the rest we
* want inputs and outputs that may cause a value to change. */
/* For synthesis or always_comb/latch we want just the inputs,
* but for the rest we want inputs and outputs that may cause
* a value to change. */
extern bool synthesis; /* Synthesis flag from main.cc */
bool rem_out = false;
if (synthesis) {
if (synthesis || search_funcs_) {
rem_out = true;
}
NexusSet*nset = enet->nex_input(rem_out);
// If this is an always_comb/latch then we need an implicit T0
// trigger of the event expression.
if (search_funcs_) wa->set_t0_trigger();
NexusSet*nset = enet->nex_input(rem_out, search_funcs_);
if (nset == 0) {
cerr << get_fileline() << ": error: Unable to elaborate:"
<< endl;
@ -4474,6 +4472,8 @@ NetProc* PEventStatement::elaborate_wait(Design*des, NetScope*scope,
/* Create an event wait and an otherwise unreferenced
event variable to force a perpetual wait. */
NetEvent*wait_event = new NetEvent(scope->local_symbol());
wait_event->set_line(*this);
wait_event->local_flag(true);
scope->add_event(wait_event);
NetEvWait*wait = new NetEvWait(0);
@ -4494,6 +4494,8 @@ NetProc* PEventStatement::elaborate_wait(Design*des, NetScope*scope,
eval_expr(expr);
NetEvent*wait_event = new NetEvent(scope->local_symbol());
wait_event->set_line(*this);
wait_event->local_flag(true);
scope->add_event(wait_event);
NetEvWait*wait = new NetEvWait(0 /* noop */);
@ -5364,7 +5366,10 @@ bool PProcess::elaborate(Design*des, NetScope*scope) const
gets into its wait statement before non-combinational
code is executed. */
do {
if (top->type() != IVL_PR_ALWAYS)
if ((top->type() != IVL_PR_ALWAYS) &&
(top->type() != IVL_PR_ALWAYS_COMB) &&
(top->type() != IVL_PR_ALWAYS_FF) &&
(top->type() != IVL_PR_ALWAYS_LATCH))
break;
NetEvWait*st = dynamic_cast<NetEvWait*>(top->statement());
@ -5411,19 +5416,7 @@ void PSpecPath::elaborate(Design*des, NetScope*scope) const
ndelays = delays.size();
if (ndelays > 12) ndelays = 12;
/* Print a warning if we find default and `timescale based
* delays in the design, since this is likely an error. */
if (scope->time_from_timescale()) dly_used_timescale = true;
else dly_used_no_timescale = true;
if (display_ts_dly_warning &&
dly_used_no_timescale && dly_used_timescale) {
cerr << "warning: Found both default and "
"`timescale based delays. Use" << endl;
cerr << " -Wtimescale to find the "
"module(s) with no `timescale." << endl;
display_ts_dly_warning = false;
}
check_for_inconsistent_delays(scope);
/* Elaborate the delay values themselves. Remember to scale
them for the timescale/precision of the scope. */
@ -5691,6 +5684,10 @@ bool PPackage::elaborate(Design*des, NetScope*scope) const
// Elaborate class definitions.
elaborate_classes(des, scope, classes);
// Elaborate the variable initialization statements, making a
// single initial process out of them.
result_flag &= elaborate_var_inits_(des, scope);
return result_flag;
}
@ -6123,14 +6120,17 @@ class later_defparams : public elaborator_work_item_t {
bool Design::check_proc_delay() const
{
bool result_flag = true;
bool result = false;
for (const NetProcTop*pr = procs_ ; pr ; pr = pr->next_) {
/* If this is an always block and we have no or zero delay then
* a runtime infinite loop will happen. If we possible have some
/* If this is an always process and we have no or zero delay then
* a runtime infinite loop will happen. If we possibly have some
* delay then print a warning that an infinite loop is possible.
*/
if (pr->type() == IVL_PR_ALWAYS) {
if ((pr->type() == IVL_PR_ALWAYS) ||
(pr->type() == IVL_PR_ALWAYS_COMB) ||
(pr->type() == IVL_PR_ALWAYS_FF) ||
(pr->type() == IVL_PR_ALWAYS_LATCH)) {
DelayType dly_type = pr->statement()->delay_type();
if (dly_type == NO_DELAY || dly_type == ZERO_DELAY) {
@ -6138,7 +6138,7 @@ bool Design::check_proc_delay() const
<< " statement does not have any delay." << endl;
cerr << pr->get_fileline() << ": : A runtime"
<< " infinite loop will occur." << endl;
result_flag = false;
result = true;
} else if (dly_type == POSSIBLE_DELAY && warn_inf_loop) {
cerr << pr->get_fileline() << ": warning: always"
@ -6146,6 +6146,38 @@ bool Design::check_proc_delay() const
cerr << pr->get_fileline() << ": : A runtime"
<< " infinite loop may be possible." << endl;
}
// The always_comb/ff/latch processes also have special
// delay rules that need to be checked.
if ((pr->type() == IVL_PR_ALWAYS_COMB) ||
(pr->type() == IVL_PR_ALWAYS_FF) ||
(pr->type() == IVL_PR_ALWAYS_LATCH)) {
const NetEvWait *wait = dynamic_cast<const NetEvWait*> (pr->statement());
if (! wait) {
// The always_comb/latch processes have an event
// control added automatically by the compiler.
assert(pr->type() == IVL_PR_ALWAYS_FF);
cerr << pr->get_fileline() << ": error: the "
<< "first statement of an always_ff must "
<< "be an event control." << endl;
result = true;
} else if (wait->statement()->delay_type(true) != NO_DELAY) {
cerr << pr->get_fileline() << ": error: there "
<< "must ";
if (pr->type() == IVL_PR_ALWAYS_FF) {
cerr << "only be a single event control "
<< "and no blocking delays in an "
<< "always_ff process.";
} else {
cerr << "be no event controls or blocking "
<< "delays in an always_comb/latch "
<< "process.";
}
cerr << endl;
result = true;
}
}
}
/* If this is a final block it must not have a delay,
@ -6155,37 +6187,287 @@ bool Design::check_proc_delay() const
if (pr->type() == IVL_PR_FINAL) {
DelayType dly_type = pr->statement()->delay_type();
if (dly_type != NO_DELAY && dly_type != ZERO_DELAY) {
if (dly_type != NO_DELAY) {
cerr << pr->get_fileline() << ": error: final"
<< " statement contains a delay." << endl;
result_flag = false;
result = true;
}
}
}
return result_flag;
return result;
}
void Design::root_elaborate(void)
static void print_nexus_name(const Nexus*nex)
{
for (map<perm_string,netclass_t*>::const_iterator cur = classes_.begin()
; cur != classes_.end() ; ++ cur) {
netclass_t*cur_class = cur->second;
PClass*cur_pclass = class_to_pclass_[cur_class];
cur_class->elaborate(this, cur_pclass);
}
for (map<NetScope*,PTaskFunc*>::iterator cur = root_tasks_.begin()
; cur != root_tasks_.end() ; ++ cur) {
if (debug_elaborate) {
cerr << cur->second->get_fileline() << ": Design::root_elaborate: "
<< "Elaborate for root task/func " << scope_path(cur->first) << endl;
for (const Link*cur = nex->first_nlink(); cur; cur = cur->next_nlink()) {
if (cur->get_dir() != Link::OUTPUT) continue;
const NetPins*obj = cur->get_obj();
// For a NetNet (signal) just use the name.
if (const NetNet*net = dynamic_cast<const NetNet*>(obj)) {
cerr << net->name();
return;
// For a NetPartSelect calculate the name.
} else if (const NetPartSelect*ps = dynamic_cast<const NetPartSelect*>(obj)) {
assert(ps->pin_count() >= 2);
assert(ps->pin(1).get_dir() == Link::INPUT);
assert(ps->pin(1).is_linked());
print_nexus_name(ps->pin(1).nexus());
cerr << "[]";
return;
// For a NetUReduce calculate the name.
} else if (const NetUReduce*reduce = dynamic_cast<const NetUReduce*>(obj)) {
assert(reduce->pin_count() == 2);
assert(reduce->pin(1).get_dir() == Link::INPUT);
assert(reduce->pin(1).is_linked());
switch (reduce->type()) {
case NetUReduce::AND:
cerr << "&";
break;
case NetUReduce::OR:
cerr << "|";
break;
case NetUReduce::XOR:
cerr << "^";
break;
case NetUReduce::NAND:
cerr << "~&";
break;
case NetUReduce::NOR:
cerr << "~|";
break;
case NetUReduce::XNOR:
cerr << "~^";
break;
case NetUReduce::NONE:
assert(0);
}
print_nexus_name(reduce->pin(1).nexus());
return;
} else if (const NetLogic*logic = dynamic_cast<const NetLogic*>(obj)) {
assert(logic->pin_count() >= 2);
assert(logic->pin(1).get_dir() == Link::INPUT);
assert(logic->pin(1).is_linked());
switch (logic->type()) {
case NetLogic::NOT:
cerr << "~";
break;
default:
// The other operators should never be used here,
// so just return the nexus name.
cerr << nex->name();
return;
}
print_nexus_name(logic->pin(1).nexus());
return;
}
// Use the following to find the type of anything that may be missing:
// cerr << "(" << typeid(*obj).name() << ") ";
}
// Otherwise just use the nexus name so somthing is printed.
cerr << nex->name();
}
cur->second->elaborate(this, cur->first);
static void print_event_probe_name(const NetEvProbe *prb)
{
assert(prb->pin_count() == 1);
assert(prb->pin(0).get_dir() == Link::INPUT);
assert(prb->pin(0).is_linked());
print_nexus_name(prb->pin(0).nexus());
}
static void check_event_probe_width(const LineInfo *info, const NetEvProbe *prb)
{
assert(prb->pin_count() == 1);
assert(prb->pin(0).get_dir() == Link::INPUT);
assert(prb->pin(0).is_linked());
if (prb->edge() == NetEvProbe::ANYEDGE) return;
if (prb->pin(0).nexus()->vector_width() > 1) {
cerr << info->get_fileline() << " Warning: Synthesis wants "
"the sensitivity list expressions for '";
switch (prb->edge()) {
case NetEvProbe::POSEDGE:
cerr << "posedge ";
break;
case NetEvProbe::NEGEDGE:
cerr << "negedge ";
break;
default:
break;
}
print_nexus_name(prb->pin(0).nexus());
cerr << "' to be a single bit." << endl;
}
}
static void check_ff_sensitivity(const NetProc* statement)
{
const NetEvWait *evwt = dynamic_cast<const NetEvWait*> (statement);
// We have already checked for and reported if the first statmemnt is
// not a wait.
if (! evwt) return;
for (unsigned cevt = 0; cevt < evwt->nevents(); cevt += 1) {
const NetEvent *evt = evwt->event(cevt);
for (unsigned cprb = 0; cprb < evt->nprobe(); cprb += 1) {
const NetEvProbe *prb = evt->probe(cprb);
check_event_probe_width(evwt, prb);
if (prb->edge() == NetEvProbe::ANYEDGE) {
cerr << evwt->get_fileline() << " Warning: Synthesis "
"requires the sensitivity list of an "
"always_ff process to only be edge "
"sensitive. ";
print_event_probe_name(prb);
cerr << " is missing a pos/negedge." << endl;
}
}
}
}
/*
* Check to see if the always_* processes only contain synthesizable
* constructs.
*/
bool Design::check_proc_synth() const
{
bool result = false;
for (const NetProcTop*pr = procs_ ; pr ; pr = pr->next_) {
if ((pr->type() == IVL_PR_ALWAYS_COMB) ||
(pr->type() == IVL_PR_ALWAYS_FF) ||
(pr->type() == IVL_PR_ALWAYS_LATCH)) {
result |= pr->statement()->check_synth(pr->type(),
pr->scope());
if (pr->type() == IVL_PR_ALWAYS_FF) {
check_ff_sensitivity(pr->statement());
}
}
}
return result;
}
/*
* Check whether all design elements have an explicit timescale or all
* design elements use the default timescale. If a mixture of explicit
* and default timescales is found, a warning message is output. Note
* that we only need to check the top level design elements - nested
* design elements will always inherit the timescale from their parent
* if they don't have any local timescale declarations.
*
* NOTE: Strictly speaking, this should be an error for SystemVerilog
* (1800-2012 section 3.14.2).
*/
static void check_timescales(bool&some_explicit, bool&some_implicit,
const PScope*scope)
{
if (scope->time_unit_is_default)
some_implicit = true;
else
some_explicit = true;
if (scope->time_prec_is_default)
some_implicit = true;
else
some_explicit = true;
}
static void check_timescales()
{
bool some_explicit = false;
bool some_implicit = false;
map<perm_string,Module*>::iterator mod;
for (mod = pform_modules.begin(); mod != pform_modules.end(); ++mod) {
const Module*mp = (*mod).second;
check_timescales(some_explicit, some_implicit, mp);
if (some_explicit && some_implicit)
break;
}
map<perm_string,PPackage*>::iterator pkg;
if (gn_system_verilog() && !(some_explicit && some_implicit)) {
for (pkg = pform_packages.begin(); pkg != pform_packages.end(); ++pkg) {
const PPackage*pp = (*pkg).second;
check_timescales(some_explicit, some_implicit, pp);
if (some_explicit && some_implicit)
break;
}
}
if (gn_system_verilog() && !(some_explicit && some_implicit)) {
for (unsigned idx = 0; idx < pform_units.size(); idx += 1) {
const PPackage*pp = pform_units[idx];
// We don't need a timescale if the compilation unit
// contains no items outside a design element.
if (pp->parameters.empty() &&
pp->localparams.empty() &&
pp->wires.empty() &&
pp->tasks.empty() &&
pp->funcs.empty() &&
pp->classes.empty())
continue;
check_timescales(some_explicit, some_implicit, pp);
if (some_explicit && some_implicit)
break;
}
}
if (!(some_explicit && some_implicit))
return;
if (gn_system_verilog()) {
cerr << "warning: "
<< "Some design elements have no explicit time unit and/or"
<< endl;
cerr << " : "
<< "time precision. This may cause confusing timing results."
<< endl;
cerr << " : "
<< "Affected design elements are:"
<< endl;
} else {
cerr << "warning: "
<< "Some modules have no timescale. This may cause"
<< endl;
cerr << " : "
<< "confusing timing results. Affected modules are:"
<< endl;
}
for (mod = pform_modules.begin(); mod != pform_modules.end(); ++mod) {
Module*mp = (*mod).second;
if (mp->has_explicit_timescale())
continue;
cerr << " : -- module " << (*mod).first
<< " declared here: " << mp->get_fileline() << endl;
}
if (!gn_system_verilog())
return;
for (pkg = pform_packages.begin(); pkg != pform_packages.end(); ++pkg) {
PPackage*pp = (*pkg).second;
if (pp->has_explicit_timescale())
continue;
cerr << " : -- package " << (*pkg).first
<< " declared here: " << pp->get_fileline() << endl;
}
for (unsigned idx = 0; idx < pform_units.size(); idx += 1) {
PPackage*pp = pform_units[idx];
if (pp->has_explicit_timescale())
continue;
if (pp->parameters.empty() &&
pp->localparams.empty() &&
pp->wires.empty() &&
pp->tasks.empty() &&
pp->funcs.empty() &&
pp->classes.empty())
continue;
cerr << " : -- compilation unit";
if (pform_units.size() > 1) {
cerr << " from: " << pp->get_file();
}
cerr << endl;
}
}
/*
@ -6207,8 +6489,13 @@ struct root_elem {
Design* elaborate(list<perm_string>roots)
{
unsigned npackages = pform_packages.size();
if (gn_system_verilog())
npackages += pform_units.size();
vector<struct root_elem> root_elems(roots.size());
vector<struct pack_elem> pack_elems(pform_packages.size());
vector<struct pack_elem> pack_elems(npackages);
map<LexicalScope*,NetScope*> unit_scopes;
bool rc = true;
unsigned i = 0;
@ -6216,23 +6503,36 @@ Design* elaborate(list<perm_string>roots)
// module and elaborate what I find.
Design*des = new Design;
// Elaborate enum sets in $root scope.
elaborate_rootscope_enumerations(des);
// Elaborate the compilation unit scopes. From here on, these are
// treated as an additional set of packages.
if (gn_system_verilog()) {
for (i = 0; i < pform_units.size(); i += 1) {
PPackage*unit = pform_units[i];
NetScope*scope = des->make_package_scope(unit->pscope_name(), 0, true);
scope->set_line(unit);
set_scope_timescale(des, scope, unit);
// Elaborate tasks and functions in $root scope.
elaborate_rootscope_tasks(des);
elaborator_work_item_t*es = new elaborate_package_t(des, scope, unit);
des->elaboration_work_list.push_back(es);
// Elaborate classes in $root scope.
elaborate_rootscope_classes(des);
pack_elems[i].pack = unit;
pack_elems[i].scope = scope;
unit_scopes[unit] = scope;
}
}
// Elaborate the packages. Package elaboration is simpler
// because there are fewer sub-scopes involved.
i = 0;
// because there are fewer sub-scopes involved. Note that
// in SystemVerilog, packages are not allowed to refer to
// the compilation unit scope, but the VHDL preprocessor
// assumes they can.
for (map<perm_string,PPackage*>::iterator pac = pform_packages.begin()
; pac != pform_packages.end() ; ++ pac) {
ivl_assert(*pac->second, pac->first == pac->second->pscope_name());
NetScope*scope = des->make_package_scope(pac->first);
NetScope*unit_scope = unit_scopes[pac->second->parent_scope()];
NetScope*scope = des->make_package_scope(pac->first, unit_scope, false);
scope->set_line(pac->second);
set_scope_timescale(des, scope, pac->second);
@ -6263,9 +6563,13 @@ Design* elaborate(list<perm_string>roots)
// Get the module definition for this root instance.
Module *rmod = (*mod).second;
// Get the compilation unit scope for this module.
NetScope*unit_scope = unit_scopes[rmod->parent_scope()];
// Make the root scope. This makes a NetScope object and
// pushes it into the list of root scopes in the Design.
NetScope*scope = des->make_root_scope(*root, rmod->program_block,
NetScope*scope = des->make_root_scope(*root, unit_scope,
rmod->program_block,
rmod->is_interface);
// Collect some basic properties of this scope from the
@ -6335,6 +6639,10 @@ Design* elaborate(list<perm_string>roots)
if (des->errors > 0)
return des;
// Now we have the full design, check for timescale inconsistencies.
if (warn_timescale)
check_timescales();
if (debug_elaborate) {
cerr << "<toplevel>: elaborate: "
<< "Start calling Package elaborate_sig methods." << endl;
@ -6363,8 +6671,6 @@ Design* elaborate(list<perm_string>roots)
<< "Start calling $root elaborate_sig methods." << endl;
}
des->root_elaborate_sig();
if (debug_elaborate) {
cerr << "<toplevel>: elaborate: "
<< "Start calling root module elaborate_sig methods." << endl;
@ -6426,8 +6732,6 @@ Design* elaborate(list<perm_string>roots)
rc &= pkg->elaborate(des, scope);
}
des->root_elaborate();
for (i = 0; i < root_elems.size(); i++) {
Module *rmod = root_elems[i].mod;
NetScope *scope = root_elems[i].scope;
@ -6442,10 +6746,11 @@ Design* elaborate(list<perm_string>roots)
// Now that everything is fully elaborated verify that we do
// not have an always block with no delay (an infinite loop),
// or a final block with a delay.
if (des->check_proc_delay() == false) {
delete des;
des = 0;
}
bool has_failure = des->check_proc_delay();
// Check to see if the always_comb/ff/latch processes only have
// synthesizable constructs
has_failure |= des->check_proc_synth();
if (debug_elaborate) {
cerr << "<toplevel>" << ": debug: "
@ -6453,5 +6758,10 @@ Design* elaborate(list<perm_string>roots)
<< des->find_root_scopes().size() << " root scopes " << endl;
}
if (has_failure) {
delete des;
des = 0;
}
return des;
}

20
emit.cc
View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2016 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-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
@ -510,24 +510,12 @@ int Design::emit(struct target_t*tgt) const
if (tgt->start_design(this) == false)
return -2;
for (map<NetScope*,PTaskFunc*>::const_iterator scope = root_tasks_.begin()
; scope != root_tasks_.end() ; ++ scope) {
scope->first->emit_scope(tgt);
}
// enumerate package scopes
for (map<perm_string,NetScope*>::const_iterator scope = packages_.begin()
; scope != packages_.end() ; ++ scope) {
scope->second->emit_scope(tgt);
}
for (map<perm_string,netclass_t*>::const_iterator cur = classes_.begin()
; cur != classes_.end() ; ++cur) {
const NetScope*use_scope = cur->second->class_scope();
cur->second->emit_scope(tgt);
tgt->class_type(use_scope, cur->second);
}
// enumerate root scopes
for (list<NetScope*>::const_iterator scope = root_scopes_.begin()
; scope != root_scopes_.end(); ++ scope ) {
@ -552,12 +540,6 @@ 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);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2016 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2018 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
@ -570,11 +570,11 @@ NetEConst* NetEBComp::eval_eqeq_(bool ne_flag, const NetExpr*le, const NetExpr*r
const verinum::V ne_res = ne_flag? verinum::V1 : verinum::V0;
verinum::V res = eq_res;
unsigned top = lv.len();
if (rv.len() < top)
top = rv.len();
for (unsigned idx = 0 ; idx < top ; idx += 1) {
// The two expressions should already be padded to the same size.
ivl_assert(*this, lv.len() == rv.len());
for (unsigned idx = 0 ; idx < lv.len() ; idx += 1) {
bool x_bit_present = false;
@ -611,60 +611,6 @@ NetEConst* NetEBComp::eval_eqeq_(bool ne_flag, const NetExpr*le, const NetExpr*r
}
}
if (res != verinum::Vx) {
verinum::V lpad = verinum::V0;
verinum::V rpad = verinum::V0;
if (lv.has_sign() && lv.get(lv.len()-1) == verinum::V1)
lpad = verinum::V1;
if (rv.has_sign() && rv.get(rv.len()-1) == verinum::V1)
rpad = verinum::V1;
for (unsigned idx = top ; idx < lv.len() ; idx += 1)
switch (lv.get(idx)) {
case verinum::Vx:
case verinum::Vz:
res = verinum::Vx;
break;
case verinum::V0:
if (res != verinum::Vx && rpad != verinum::V0)
res = ne_res;
break;
case verinum::V1:
if (res != verinum::Vx && rpad != verinum::V1)
res = ne_res;
break;
default:
break;
}
for (unsigned idx = top ; idx < rv.len() ; idx += 1)
switch (rv.get(idx)) {
case verinum::Vx:
case verinum::Vz:
res = verinum::Vx;
break;
case verinum::V0:
if (res != verinum::Vx && lpad != verinum::V0)
res = ne_res;
break;
case verinum::V1:
if (res != verinum::Vx && lpad != verinum::V1)
res = ne_res;
break;
default:
break;
}
}
NetEConst*result = new NetEConst(verinum(res, 1));
ivl_assert(*this, result);
return result;
@ -681,46 +627,15 @@ NetEConst* NetEBComp::eval_eqeqeq_(bool ne_flag, const NetExpr*le, const NetExpr
verinum::V res = verinum::V1;
// Find the smallest argument length.
unsigned cnt = lv.len();
if (cnt > rv.len()) cnt = rv.len();
// The two expressions should already be padded to the same size.
ivl_assert(*this, lv.len() == rv.len());
// Check the common bits.
for (unsigned idx = 0 ; idx < cnt ; idx += 1)
for (unsigned idx = 0 ; idx < lv.len() ; idx += 1)
if (lv.get(idx) != rv.get(idx)) {
res = verinum::V0;
break;
}
bool is_signed = lv.has_sign() && rv.has_sign();
// 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);
for (unsigned idx = cnt ; idx < lv.len() ; idx += 1)
if (lv.get(idx) != pad) {
res = verinum::V0;
break;
}
}
// 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);
for (unsigned idx = cnt ; idx < rv.len() ; idx += 1) {
if (rv.get(idx) != pad) {
res = verinum::V0;
break;
}
}
}
if (ne_flag) {
if (res == verinum::V0) res = verinum::V1;
else res = verinum::V0;
@ -731,6 +646,55 @@ NetEConst* NetEBComp::eval_eqeqeq_(bool ne_flag, const NetExpr*le, const NetExpr
return result;
}
NetEConst* NetEBComp::eval_weqeq_(bool ne_flag, const NetExpr*le, const NetExpr*re) const
{
const NetEConst*lc = dynamic_cast<const NetEConst*>(le);
const NetEConst*rc = dynamic_cast<const NetEConst*>(re);
if (lc == 0 || rc == 0) return 0;
const verinum&lv = lc->value();
const verinum&rv = rc->value();
const verinum::V eq_res = ne_flag ? verinum::V0 : verinum::V1;
const verinum::V ne_res = ne_flag ? verinum::V1 : verinum::V0;
verinum::V res = eq_res;
// The two expressions should already be padded to the same size.
ivl_assert(*this, lv.len() == rv.len());
for (unsigned idx = 0 ; idx < lv.len() ; idx += 1) {
// An X or Z in the R-value matches any L-value.
switch (rv.get(idx)) {
case verinum::Vx:
case verinum::Vz:
continue;
default:
break;
}
// An X or Z in the L-value that is not matches by an R-value X/Z returns undefined.
switch (lv.get(idx)) {
case verinum::Vx:
case verinum::Vz:
res = verinum::Vx;
continue;
default:
break;
}
// A hard (0/1) mismatch gives a not-equal result.
if (rv.get(idx) != lv.get(idx)) {
res = ne_res;
break;
}
}
NetEConst*result = new NetEConst(verinum(res, 1));
ivl_assert(*this, result);
return result;
}
NetEConst* NetEBComp::eval_arguments_(const NetExpr*l, const NetExpr*r) const
{
NetEConst*res = 0;
@ -744,6 +708,10 @@ NetEConst* NetEBComp::eval_arguments_(const NetExpr*l, const NetExpr*r) const
res = eval_eqeq_(false, l, r);
break;
case 'w': // Wild equality (==?)
res = eval_weqeq_(false, l, r);
break;
case 'G': // >=
res = eval_gteq_(l, r);
break;
@ -760,6 +728,10 @@ NetEConst* NetEBComp::eval_arguments_(const NetExpr*l, const NetExpr*r) const
res = eval_eqeq_(true, l, r);
break;
case 'W': // Wild not-equal (!=?)
res = eval_weqeq_(true, l, r);
break;
case '<': // Less than
res = eval_less_(l, r);
break;
@ -1102,6 +1074,7 @@ NetEConst* NetEBShift::eval_arguments_(const NetExpr*l, const NetExpr*r) const
break;
case 'r':
lv.has_sign(false);
// fallthrough
case 'R':
val = cast_to_width(lv >> shift, wid);
break;
@ -1553,6 +1526,7 @@ NetEConst* NetEUReduce::eval_arguments_(const NetExpr*ex) const
case 'A':
invert = true;
// fallthrough
case '&': {
res = verinum::V1;
for (unsigned idx = 0 ; idx < val.len() ; idx += 1)
@ -1562,6 +1536,7 @@ NetEConst* NetEUReduce::eval_arguments_(const NetExpr*ex) const
case 'N':
invert = true;
// fallthrough
case '|': {
res = verinum::V0;
for (unsigned idx = 0 ; idx < val.len() ; idx += 1)
@ -1571,6 +1546,7 @@ NetEConst* NetEUReduce::eval_arguments_(const NetExpr*ex) const
case 'X':
invert = true;
// fallthrough
case '^': {
/* Reduction XOR. */
unsigned ones = 0, unknown = 0;
@ -1622,6 +1598,7 @@ NetExpr* NetECast::eval_arguments_(const NetExpr*ex) const
res_val = cast_to_width(res_val, expr_width());
res = new NetEConst(res_val);
}
// fallthrough
case 'v':
if (const NetECReal*val = dynamic_cast<const NetECReal*>(ex)) {
verinum res_val(val->value().as_double(), false);
@ -1936,15 +1913,111 @@ NetExpr* NetESFunc::evaluate_min_max_(ID id, const NetExpr*arg0_,
return res;
}
NetEConst* NetESFunc::evaluate_countbits_(const NetExpr* /*arg0*/,
const NetExpr* /*arg1*/) const
static void no_string_arg(const NetESFunc*info, unsigned arg_num)
{
return 0;
cerr << info->get_fileline() << ": error: constant function "
<< info->name() << "() does not support a string argument ("
<< arg_num+1 << ")." << endl;
}
NetEConst* NetESFunc::evaluate_countones_(const NetExpr* /*arg*/) const
NetEConst* NetESFunc::evaluate_countbits_() const
{
return 0;
const NetEConst*tmpi = dynamic_cast<const NetEConst*>(parms_[0]);
NetEConst*res = 0;
if (tmpi) {
verinum value = tmpi->value();
if (value.is_string()) {
no_string_arg(this, 0);
return 0;
}
/* Find which values need to be counted. */
bool count_0 = false;
bool count_1 = false;
bool count_z = false;
bool count_x = false;
for (unsigned arg=1; arg < parms_.size(); ++arg) {
const NetEConst*argi = dynamic_cast<const NetEConst*>(parms_[arg]);
if (! argi) return 0;
verinum check_for = argi->value();
if (check_for.is_string()) {
no_string_arg(this, arg);
return 0;
}
switch (check_for[0]) {
case verinum::V0:
count_0 = true;
break;
case verinum::V1:
count_1 = true;
break;
case verinum::Vz:
count_z = true;
break;
case verinum::Vx:
count_x = true;
break;
}
}
/* Search each bit of the vector looking for the values to
* be counted. */
int count = 0;
for (unsigned bit=0; bit < value.len(); ++bit) {
switch (value[bit]) {
case verinum::V0:
if (count_0) ++count;
break;
case verinum::V1:
if (count_1) ++count;
break;
case verinum::Vz:
if (count_z) ++count;
break;
case verinum::Vx:
if (count_x) ++count;
break;
}
}
verinum tmp (count, integer_width);
tmp.has_sign(true);
res = new NetEConst(tmp);
ivl_assert(*this, res);
}
return res;
}
NetEConst* NetESFunc::evaluate_countones_(const NetExpr* arg) const
{
const NetEConst*tmpi = dynamic_cast<const NetEConst*>(arg);
NetEConst*res = 0;
if (tmpi) {
verinum value = tmpi->value();
int count = 0;
if (value.is_string()) {
no_string_arg(this, 0);
return 0;
}
for (unsigned bit=0; bit < value.len(); ++bit) {
if (value[bit] == verinum::V1) ++count;
}
verinum tmp (count, integer_width);
tmp.has_sign(true);
res = new NetEConst(tmp);
ivl_assert(*this, res);
}
return res;
}
/* Get the total number of dimensions for the given expression. */
@ -1967,19 +2040,92 @@ NetEConst* NetESFunc::evaluate_dimensions_(const NetExpr*arg) const
return new NetEConst(verinum(verinum(res), integer_width));
}
NetEConst* NetESFunc::evaluate_isunknown_(const NetExpr* /*arg*/) const
NetEConst* NetESFunc::evaluate_isunknown_(const NetExpr* arg) const
{
return 0;
const NetEConst*tmpi = dynamic_cast<const NetEConst*>(arg);
NetEConst*res = 0;
if (tmpi) {
verinum value = tmpi->value();
unsigned is_unknown = 1;
if (value.is_string()) {
no_string_arg(this, 0);
return 0;
}
if (value.is_defined()) is_unknown = 0;
verinum tmp (is_unknown, 1U);
tmp.has_sign(false);
res = new NetEConst(tmp);
ivl_assert(*this, res);
}
return res;
}
NetEConst* NetESFunc::evaluate_onehot_(const NetExpr* /*arg*/) const
static bool is_onehot(verinum&value, bool zero_is_okay)
{
return 0;
bool found_a_one = false;
for (unsigned bit=0; bit < value.len(); ++bit) {
if (value[bit] == verinum::V1) {
if (found_a_one) return false;
found_a_one = true;
}
}
/* If no one bit was found return true if zero is okay. */
if (zero_is_okay) found_a_one = true;
return found_a_one;
}
NetEConst* NetESFunc::evaluate_onehot0_(const NetExpr* /*arg*/) const
NetEConst* NetESFunc::evaluate_onehot_(const NetExpr* arg) const
{
return 0;
const NetEConst*tmpi = dynamic_cast<const NetEConst*>(arg);
NetEConst*res = 0;
if (tmpi) {
verinum value = tmpi->value();
if (value.is_string()) {
no_string_arg(this, 0);
return 0;
}
verinum tmp (is_onehot(value, false), 1U);
tmp.has_sign(false);
res = new NetEConst(tmp);
ivl_assert(*this, res);
}
return res;
}
NetEConst* NetESFunc::evaluate_onehot0_(const NetExpr* arg) const
{
const NetEConst*tmpi = dynamic_cast<const NetEConst*>(arg);
NetEConst*res = 0;
if (tmpi) {
verinum value = tmpi->value();
if (value.is_string()) {
no_string_arg(this, 0);
return 0;
}
verinum tmp (is_onehot(value, true), 1U);
tmp.has_sign(false);
res = new NetEConst(tmp);
ivl_assert(*this, res);
}
return res;
}
/* Get the number of unpacked dimensions for the given expression. */
@ -2151,7 +2297,7 @@ NetExpr* NetESFunc::evaluate_two_arg_(ID id, const NetExpr*arg0,
{
switch (id) {
case CTBITS:
return evaluate_countbits_(arg0, arg1);
return evaluate_countbits_();
/* The array functions are handled together. */
case HIGH:
case INCR:
@ -2222,12 +2368,12 @@ NetESFunc::ID NetESFunc::built_in_id_() const
built_in_func["$unpacked_dimensions" ] = UPDIMS;
}
/* These are available in 1800-2009 and later. */
/* This is available in 1800-2009 and later. */
if (funcs_need_init && (generation_flag >= GN_VER2009)) {
built_in_func["$countones" ] = CTONES;
}
/* These are available in 1800-2012 and later. */
/* This is available in 1800-2012 and later. */
if (funcs_need_init && (generation_flag >= GN_VER2012)) {
built_in_func["$countbits" ] = CTBITS;
}
@ -2254,7 +2400,7 @@ NetESFunc::ID NetESFunc::built_in_id_() const
NetExpr* NetESFunc::eval_tree()
{
/* Get the ID for this system function if it is can be used as a
/* Get the ID for this system function if it can be used as a
* constant function. */
ID id = built_in_id_();
if (id == NOT_BUILT_IN) return 0;
@ -2262,8 +2408,9 @@ NetExpr* NetESFunc::eval_tree()
switch (parms_.size()) {
case 1:
if (! takes_nargs_(id, 1)) {
cerr << get_fileline() << ": error: " << name_
<< "() does not support a single argument." << endl;
cerr << get_fileline() << ": error: constant function "
<< name_ << "() does not support a single argument."
<< endl;
return 0;
}
eval_expr(parms_[0]);
@ -2271,8 +2418,9 @@ NetExpr* NetESFunc::eval_tree()
case 2:
if (! takes_nargs_(id, 2)) {
cerr << get_fileline() << ": error: " << name_
<< "() does not support two arguments." << endl;
cerr << get_fileline() << ": error: constant function "
<< name_ << "() does not support two arguments."
<< endl;
return 0;
}
eval_expr(parms_[0]);
@ -2282,15 +2430,21 @@ NetExpr* NetESFunc::eval_tree()
default:
/* Check to see if the function was called correctly. */
if (! takes_nargs_(id, parms_.size())) {
cerr << get_fileline() << ": error: " << name_
<< "() does not support " << parms_.size()
cerr << get_fileline() << ": error: constant function "
<< name_ << "() does not support " << parms_.size()
<< " arguments." << endl;
return 0;
}
// HERE: Need to add support for a multi argument $countbits().
cerr << get_fileline() << ": sorry: functions with "
<< parms_.size() << " arguments are not supported: "
<< name_ << "()." << endl;
if (id == CTBITS) {
for (unsigned bit = 0; bit < parms_.size(); ++bit) {
eval_expr(parms_[bit]);
}
return evaluate_countbits_();
} else {
cerr << get_fileline() << ": sorry: constant functions with "
<< parms_.size() << " arguments are not supported: "
<< name_ << "()." << endl;
}
return 0;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2015 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2018 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
@ -274,7 +274,18 @@ NetNet* NetEBComp::synthesize(Design*des, NetScope*scope, NetExpr*root)
if (op_ == 'E' || op_ == 'N') {
NetCaseCmp*gate = new NetCaseCmp(scope, scope->local_symbol(),
width, op_=='E'?NetCaseCmp::EEQ:NetCaseCmp::NEQ);
width, op_=='E' ? NetCaseCmp::EEQ : NetCaseCmp::NEQ);
gate->set_line(*this);
connect(gate->pin(0), osig->pin(0));
connect(gate->pin(1), lsig->pin(0));
connect(gate->pin(2), rsig->pin(0));
des->add_node(gate);
return osig;
}
if (op_ == 'w' || op_ == 'W') {
NetCaseCmp*gate = new NetCaseCmp(scope, scope->local_symbol(),
width, op_=='w' ? NetCaseCmp::WEQ : NetCaseCmp::WNE);
gate->set_line(*this);
connect(gate->pin(0), osig->pin(0));
connect(gate->pin(1), lsig->pin(0));
@ -335,6 +346,7 @@ NetNet* NetEBComp::synthesize(Design*des, NetScope*scope, NetExpr*root)
des->errors += 1;
return 0;
}
// fallthrough
case 'e': // ==
connect(dev->pin_AEB(), osig->pin(0));
break;
@ -353,6 +365,7 @@ NetNet* NetEBComp::synthesize(Design*des, NetScope*scope, NetExpr*root)
des->errors += 1;
return 0;
}
// fallthrough
case 'n': // !=
connect(dev->pin_ANEB(), osig->pin(0));
break;
@ -1347,6 +1360,7 @@ static NetEvWait* make_func_trigger(Design*des, NetScope*scope, NetExpr*root)
if (nset && (nset->size() > 0)) {
NetEvent*ev = new NetEvent(scope->local_symbol());
ev->set_line(*root);
ev->local_flag(true);
NetEvProbe*pr = new NetEvProbe(scope, scope->local_symbol(),
ev, NetEvProbe::ANYEDGE,

View File

@ -1,4 +1,4 @@
.TH iverilog-vpi 1 "May 10th, 2015" "" "Version %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

View File

@ -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"
;;
@ -92,6 +96,11 @@ do
exit;
;;
--ccflags)
echo "$CXXFLAGS"
exit;
;;
--ldflags)
echo "$LDFLAGS"
exit;
@ -148,4 +157,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

View File

@ -294,6 +294,7 @@ ivl_stmt_lval
ivl_stmt_lvals
ivl_stmt_lwidth
ivl_stmt_name
ivl_stmt_needs_t0_trigger
ivl_stmt_nevent
ivl_stmt_opcode
ivl_stmt_parm

View File

@ -1,7 +1,7 @@
#ifndef IVL_ivl_target_H
#define IVL_ivl_target_H
/*
* Copyright (c) 2000-2016 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
@ -306,8 +306,10 @@ typedef enum ivl_lpm_type_e {
IVL_LPM_CONCAT = 16,
IVL_LPM_CONCATZ = 36, /* Transparent concat */
IVL_LPM_CMP_EEQ= 18, /* Case EQ (===) */
IVL_LPM_CMP_EQX= 37, /* Wildcard EQ (==?) */
IVL_LPM_CMP_EQX= 37, /* Wildcard EQ (casex) */
IVL_LPM_CMP_EQZ= 38, /* casez EQ */
IVL_LPM_CMP_WEQ= 41,
IVL_LPM_CMP_WNE= 42,
IVL_LPM_CMP_EQ = 10,
IVL_LPM_CMP_GE = 1,
IVL_LPM_CMP_GT = 2,
@ -353,9 +355,12 @@ typedef enum ivl_path_edge_e {
/* Processes are initial, always, or final blocks with a statement. This is
the type of the ivl_process_t object. */
typedef enum ivl_process_type_e ENUM_UNSIGNED_INT {
IVL_PR_INITIAL = 0,
IVL_PR_ALWAYS = 1,
IVL_PR_FINAL = 2
IVL_PR_INITIAL = 0,
IVL_PR_ALWAYS = 1,
IVL_PR_ALWAYS_COMB = 3,
IVL_PR_ALWAYS_FF = 4,
IVL_PR_ALWAYS_LATCH = 5,
IVL_PR_FINAL = 2
} ivl_process_type_t;
/* These are the sorts of reasons a scope may come to be. These types
@ -2100,6 +2105,7 @@ extern unsigned ivl_stmt_lineno(ivl_statement_t net);
* handle disable statements.
*
* ivl_stmt_events
* ivl_stmt_needs_t0_trigger
* ivl_stmt_nevent
* Statements that have event arguments (TRIGGER and WAIT) make
* those event objects available through these methods.
@ -2227,6 +2233,7 @@ extern ivl_expr_t ivl_stmt_delay_expr(ivl_statement_t net);
/* IVL_ST_DELAY */
extern uint64_t ivl_stmt_delay_val(ivl_statement_t net);
/* IVL_ST_WAIT IVL_ST_TRIGGER */
extern unsigned ivl_stmt_needs_t0_trigger(ivl_statement_t net);
extern unsigned ivl_stmt_nevent(ivl_statement_t net);
extern ivl_event_t ivl_stmt_events(ivl_statement_t net, unsigned idx);
/* IVL_ST_CONTRIB */

View File

@ -1,7 +1,7 @@
#ifndef IVL_ivl_target_priv_H
#define IVL_ivl_target_priv_H
/*
* Copyright (c) 2008-2014 Stephen Williams (steve@icarus.com)
* Copyright (c) 2008-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
@ -52,7 +52,6 @@ struct ivl_design_s {
// Keep arrays of root scopes.
std::map<const NetScope*,ivl_scope_t> classes;
std::map<const NetScope*,ivl_scope_t> root_tasks;
std::vector<ivl_scope_t> packages;
std::vector<ivl_scope_t> roots;

View File

@ -1,7 +1,7 @@
#ifndef IVL_globals_H
#define IVL_globals_H
/*
* Copyright (c) 1999-2014 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-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
@ -53,6 +53,9 @@ extern char dep_mode;
extern int verbose_flag;
extern int warn_redef;
extern int warn_redef_all;
/* This is the entry to the lexer. */
extern int yylex(void);

View File

@ -1,7 +1,7 @@
%option prefix="yy"
%{
/*
* Copyright (c) 1999-2016 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-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
@ -858,6 +858,25 @@ void define_macro(const char* name, const char* value, int keyword, int argc)
{
int idx;
struct define_t* def;
struct define_t* prev;
/* Verilog has a very nasty system of macros jumping from
* file to file, resulting in a global macro scope. Here
* we optionally warn about any redefinitions.
*
* If istack is empty, we are processing a configuration
* or precompiled macro file, so don't want to check for
* redefinitions - when a precompiled macro file is used,
* it will contain copies of any predefined macros.
*/
if (warn_redef && istack) {
prev = def_lookup(name);
if (prev && (warn_redef_all || (strcmp(prev->value, value) != 0))) {
emit_pathline(istack);
fprintf(stderr, "warning: redefinition of macro %s from value '%s' to '%s'\n",
name, prev->value, value);
}
}
def = malloc(sizeof(struct define_t));
def->name = strdup(name);
@ -2100,7 +2119,7 @@ void destroy_lexor(void)
{
# ifdef FLEX_SCANNER
# if YY_FLEX_MAJOR_VERSION >= 2 && YY_FLEX_MINOR_VERSION >= 5
# if defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9
# if YY_FLEX_MINOR_VERSION > 5 || defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9
yylex_destroy();
# endif
# endif

View File

@ -1,5 +1,5 @@
const char COPYRIGHT[] =
"Copyright (c) 1999-2015 Stephen Williams (steve@icarus.com)";
"Copyright (c) 1999-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
@ -98,6 +98,10 @@ int line_direct_flag = 0;
unsigned error_count = 0;
FILE *depend_file = NULL;
/* Should we warn about macro redefinitions? */
int warn_redef = 0;
int warn_redef_all = 0;
static int flist_read_flags(const char*path)
{
char line_buf[2048];
@ -282,7 +286,7 @@ int main(int argc, char*argv[])
include_dir[0] = 0; /* 0 is reserved for the current files path. */
include_dir[1] = strdup(".");
while ((opt=getopt(argc, argv, "F:f:K:Lo:p:P:vV")) != EOF) switch (opt) {
while ((opt=getopt(argc, argv, "F:f:K:Lo:p:P:vVW:")) != EOF) switch (opt) {
case 'F':
flist_read_flags(optarg);
@ -336,6 +340,15 @@ int main(int argc, char*argv[])
break;
}
case 'W':
if (strcmp(optarg, "redef-all") == 0) {
warn_redef_all = 1;
warn_redef = 1;
} else if (strcmp(optarg, "redef-chg") == 0) {
warn_redef = 1;
}
break;
case 'v':
fprintf(stderr, "Icarus Verilog Preprocessor version "
VERSION " (" VERSION_TAG ")\n\n");
@ -366,7 +379,10 @@ int main(int argc, char*argv[])
" -p<fil> - Write precompiled defines to <fil>\n"
" -P<fil> - Read precompiled defines from <fil>\n"
" -v - Verbose\n"
" -V - Print version information and quit\n",
" -V - Print version information and quit\n"
" -W<cat> - Enable extra ivlpp warning category:\n"
" o redef-all - all macro redefinitions\n"
" o redef-chg - macro definition changes\n",
argv[0]);
return flag_errors;
}

View File

@ -4,7 +4,7 @@
%{
/*
* Copyright (c) 1998-2015 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-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
@ -72,6 +72,7 @@ static const char* set_file_name(char*text)
void reset_lexor();
static void line_directive();
static void line_directive2();
static void reset_all();
verinum*make_unsized_binary(const char*txt);
verinum*make_undef_highz_dec(const char*txt);
@ -187,6 +188,8 @@ TU [munpf]
"!=" { return K_NE; }
"===" { return K_CEQ; }
"!==" { return K_CNE; }
"==?" { return K_WEQ; }
"!=?" { return K_WNE; }
"||" { return K_LOR; }
"&&" { return K_LAND; }
"&&&" { return K_TAND; }
@ -310,15 +313,6 @@ TU [munpf]
BEGIN(UDPTABLE);
break;
/* Translate these to checks if we already have or are
* outside the declaration region. */
case K_timeunit:
if (have_timeunit_decl) rc = K_timeunit_check;
break;
case K_timeprecision:
if (have_timeprec_decl) rc = K_timeprecision_check;
break;
default:
yylval.text = 0;
break;
@ -428,6 +422,12 @@ TU [munpf]
if (strcmp(yytext,"$attribute") == 0)
return KK_attribute;
if (gn_system_verilog() && strcmp(yytext,"$unit") == 0) {
yylval.package = pform_units.back();
return PACKAGE_IDENTIFIER;
}
yylval.text = strdupnew(yytext);
return SYSTEM_IDENTIFIER; }
@ -566,11 +566,7 @@ TU [munpf]
"definition." << endl;
error_count += 1;
} else {
pform_set_default_nettype(NetNet::WIRE, yylloc.text,
yylloc.first_line);
in_celldefine = false;
uc_drive = UCD_NONE;
pform_set_timescale(def_ts_units, def_ts_prec, 0, 0);
reset_all();
} }
/* Notice and handle the `unconnected_drive directive. */
@ -1597,6 +1593,18 @@ static void line_directive2()
yylloc.first_line = lineno;
}
/*
* Reset all compiler directives. This will be called when a `resetall
* directive is encountered or when a new compilation unit is started.
*/
static void reset_all()
{
pform_set_default_nettype(NetNet::WIRE, yylloc.text, yylloc.first_line);
in_celldefine = false;
uc_drive = UCD_NONE;
pform_set_timescale(def_ts_units, def_ts_prec, 0, 0);
}
extern FILE*vl_input;
void reset_lexor()
{
@ -1605,6 +1613,14 @@ void reset_lexor()
/* Announce the first file name. */
yylloc.text = set_file_name(strdupnew(vl_file.c_str()));
if (separate_compilation) {
reset_all();
if (!keyword_mask_stack.empty()) {
lexor_keyword_mask = keyword_mask_stack.back();
keyword_mask_stack.clear();
}
}
}
/*
@ -1614,7 +1630,7 @@ void destroy_lexor()
{
# ifdef FLEX_SCANNER
# if YY_FLEX_MAJOR_VERSION >= 2 && YY_FLEX_MINOR_VERSION >= 5
# if defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9
# if YY_FLEX_MINOR_VERSION > 5 || defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9
yylex_destroy();
# endif
# endif

View File

@ -32,8 +32,8 @@ static unsigned string_pool_count = 0;
StringHeap::StringHeap()
{
cell_base_ = 0;
cell_ptr_ = HEAPCELL;
cell_count_ = 0;
cell_size_ = 0;
cell_ptr_ = 0;
}
StringHeap::~StringHeap()
@ -45,20 +45,24 @@ StringHeap::~StringHeap()
const char* StringHeap::add(const char*text)
{
unsigned len = strlen(text);
assert((len+1) <= HEAPCELL);
unsigned rem = HEAPCELL - cell_ptr_;
unsigned rem = cell_size_ - cell_ptr_;
if (rem < (len+1)) {
cell_base_ = (char*)malloc(HEAPCELL);
// release any unused memory
if (rem > 0) {
cell_base_ = (char*)realloc(cell_base_, cell_ptr_);
assert(cell_base_ != 0);
}
// start new cell
cell_size_ = (len+1) > DEFAULT_CELL_SIZE ? len+1 : DEFAULT_CELL_SIZE;
cell_base_ = (char*)malloc(cell_size_);
cell_ptr_ = 0;
assert(cell_base_ != 0);
#ifdef CHECK_WITH_VALGRIND
string_pool_count += 1;
string_pool = (char **) realloc(string_pool,
string_pool_count*sizeof(char **));
string_pool[string_pool_count-1] = cell_base_;
#endif
cell_ptr_ = 0;
cell_count_ += 1;
assert(cell_base_ != 0);
}
char*res = cell_base_ + cell_ptr_;
@ -66,7 +70,7 @@ const char* StringHeap::add(const char*text)
cell_ptr_ += len;
cell_base_[cell_ptr_++] = 0;
assert(cell_ptr_ <= HEAPCELL);
assert(cell_ptr_ <= cell_size_);
return res;
}

View File

@ -78,11 +78,11 @@ class StringHeap {
perm_string make(const char*);
private:
enum { HEAPCELL = 0x10000 };
static const unsigned DEFAULT_CELL_SIZE = 0x10000;
char*cell_base_;
unsigned cell_size_;
unsigned cell_ptr_;
unsigned cell_count_;
private: // not implemented
StringHeap(const StringHeap&);

View File

@ -47,7 +47,7 @@ LDRELOCFLAGS = @LDRELOCFLAGS@
LDTARGETFLAGS = @LDTARGETFLAGS@
CPPFLAGS = $(INCLUDE_PATH) @CPPFLAGS@ @DEFS@ @PICFLAG@
CPPFLAGS = $(INCLUDE_PATH) @CPPFLAGS@ @DEFS@ -DICARUS_VPI_CONST=const @PICFLAG@
CFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CC@ @CFLAGS@
A = a_close.o a_compare_handles.o a_configure.o a_fetch_argc.o \

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002-2014 Michael Ruff (mruff at chiaro.com)
* Copyright (c) 2002-2018 Michael Ruff (mruff at chiaro.com)
* Michael Runyan (mrunyan at chiaro.com)
*
* This source code is free software; you can redistribute it
@ -42,8 +42,9 @@ typedef struct t_pli_data {
int paramvc; /* parameter number for misctf */
} s_pli_data, *p_pli_data;
static PLI_INT32 compiletf(char *);
static PLI_INT32 calltf(char *);
static PLI_INT32 compiletf(ICARUS_VPI_CONST PLI_BYTE8 *);
static PLI_INT32 calltf(ICARUS_VPI_CONST PLI_BYTE8 *);
static PLI_INT32 sizetf(ICARUS_VPI_CONST PLI_BYTE8 *);
static PLI_INT32 callback(p_cb_data);
/*
@ -150,7 +151,7 @@ void veriusertfs_register_table(p_tfcell vtable)
tf_data.tfname = tf->tfname;
tf_data.compiletf = compiletf;
tf_data.calltf = calltf;
tf_data.sizetf = (PLI_INT32 (*)(PLI_BYTE8 *))tf->sizetf;
tf_data.sizetf = sizetf;
tf_data.user_data = (char *)data;
if (pli_trace) {
@ -180,7 +181,7 @@ void veriusertfs_register_table(p_tfcell vtable)
* This function calls the veriusertfs checktf and sets up all the
* callbacks misctf requires.
*/
static PLI_INT32 compiletf(char *data)
static PLI_INT32 compiletf(ICARUS_VPI_CONST PLI_BYTE8*data)
{
p_pli_data pli;
p_tfcell tf;
@ -260,7 +261,7 @@ static PLI_INT32 compiletf(char *data)
/*
* This function is the wrapper for the veriusertfs calltf routine.
*/
static PLI_INT32 calltf(char *data)
static PLI_INT32 calltf(ICARUS_VPI_CONST PLI_BYTE8*data)
{
int rc = 0;
p_pli_data pli;
@ -283,6 +284,32 @@ static PLI_INT32 calltf(char *data)
return rc;
}
/*
* This function is the wrapper for the veriusertfs sizetf routine.
*/
static PLI_INT32 sizetf(ICARUS_VPI_CONST PLI_BYTE8*data)
{
int rc = 32;
p_pli_data pli;
p_tfcell tf;
/* cast back from opaque */
pli = (p_pli_data)data;
tf = pli->tf;
/* execute sizetf */
if (tf->sizetf) {
if (pli_trace) {
fprintf(pli_trace, "Call %s->sizetf(%d, %d)\n",
tf->tfname, tf->data, reason_sizetf);
}
rc = tf->sizetf(tf->data, reason_sizetf);
}
return rc;
}
/*
* This function is the wrapper for all the misctf callbacks
*/

View File

@ -82,36 +82,10 @@ bool load_module(const char*type)
fflush(depend_file);
}
if (ivlpp_string) {
char*cmdline = (char*)malloc(strlen(ivlpp_string) +
strlen(path) + 4);
strcpy(cmdline, ivlpp_string);
strcat(cmdline, " \"");
strcat(cmdline, path);
strcat(cmdline, "\"");
if (verbose_flag)
cerr << "Loading library file " << path << "." << endl;
if (verbose_flag)
cerr << "Executing: " << cmdline << endl<< flush;
FILE*file = popen(cmdline, "r");
if (verbose_flag)
cerr << "...parsing output from preprocessor..." << endl << flush;
pform_parse(path, file);
pclose(file);
free(cmdline);
} else {
if (verbose_flag)
cerr << "Loading library file "
<< path << "." << endl;
FILE*file = fopen(path, "r");
assert(file);
pform_parse(path, file);
fclose(file);
}
pform_parse(path);
if (verbose_flag)
cerr << "... Load module complete." << endl << flush;
@ -119,7 +93,6 @@ bool load_module(const char*type)
return true;
}
return false;
}

102
main.cc
View File

@ -1,5 +1,5 @@
const char COPYRIGHT[] =
"Copyright (c) 1998-2016 Stephen Williams (steve@icarus.com)";
"Copyright (c) 1998-2017 Stephen Williams (steve@icarus.com)";
/*
* This source code is free software; you can redistribute it
@ -140,6 +140,8 @@ void add_vpi_module(const char*name)
map<perm_string,unsigned> missing_modules;
map<perm_string,bool> library_file_map;
vector<perm_string> source_files;
list<const char*> library_suff;
list<perm_string> roots;
@ -164,6 +166,11 @@ bool warn_sens_entire_arr = false;
bool warn_anachronisms = false;
bool warn_floating_nets = false;
/*
* Ignore errors about missing modules
*/
bool ignore_missing_modules = false;
/*
* Debug message class flags.
*/
@ -174,6 +181,11 @@ bool debug_emit = false;
bool debug_synth2 = false;
bool debug_optimizer = false;
/*
* Compilation control flags.
*/
bool separate_compilation = false;
/*
* Optimization control flags.
*/
@ -570,6 +582,9 @@ static bool set_default_timescale(const char*ts_string)
*
* warnings:<string>
* Warning flag letters.
*
* ignore_missing_modules:<bool>
* true to ignore errors about missing modules
*/
bool had_timescale = false;
static void read_iconfig_file(const char*ipath)
@ -720,6 +735,10 @@ static void read_iconfig_file(const char*ipath)
break;
}
} else if (strcmp(buf, "ignore_missing_modules") == 0) {
if (strcmp(cp, "true") == 0)
ignore_missing_modules = true;
} else if (strcmp(buf, "-y") == 0) {
build_library_index(cp, CASE_SENSITIVE);
@ -765,6 +784,38 @@ static void read_iconfig_file(const char*ipath)
fclose(ifile);
}
/*
* This function reads a list of source file names. Each name starts
* with the first non-space character, and ends with the last non-space
* character. Spaces in the middle are OK.
*/
static void read_sources_file(const char*path)
{
char line_buf[2048];
FILE*fd = fopen(path, "r");
if (fd == 0) {
cerr << "ERROR: Unable to read source file list: " << path << endl;
return;
}
while (fgets(line_buf, sizeof line_buf, fd) != 0) {
char*cp = line_buf + strspn(line_buf, " \t\r\b\f");
char*tail = cp + strlen(cp);
while (tail > cp) {
if (! isspace((int)tail[-1]))
break;
tail -= 1;
tail[0] = 0;
}
if (cp < tail)
source_files.push_back(filename_strings.make(cp));
}
fclose(fd);
}
extern Design* elaborate(list <perm_string> root);
#if defined(HAVE_TIMES)
@ -851,12 +902,14 @@ int main(int argc, char*argv[])
min_typ_max_flag = TYP;
min_typ_max_warn = 10;
while ((opt = getopt(argc, argv, "C:f:hN:P:p:Vv")) != EOF) switch (opt) {
while ((opt = getopt(argc, argv, "C:F:f:hN:P:p:Vv")) != EOF) switch (opt) {
case 'C':
read_iconfig_file(optarg);
break;
case 'F':
read_sources_file(optarg);
break;
case 'f':
parm_to_flagmap(optarg);
break;
@ -909,6 +962,7 @@ int main(int argc, char*argv[])
"usage: ivl <options> <file>\n"
"options:\n"
"\t-C <name> Config file from driver.\n"
"\t-F <file> List of source files from driver.\n"
"\t-h Print usage information, and exit.\n"
"\t-N <file> Dump the elaborated netlist to <file>.\n"
"\t-P <file> Write the parsed input to <file>.\n"
@ -924,11 +978,19 @@ int main(int argc, char*argv[])
return 0;
}
if (optind == argc) {
int arg = optind;
while (arg < argc) {
perm_string path = filename_strings.make(argv[arg++]);
source_files.push_back(path);
}
if (source_files.empty()) {
cerr << "No input files." << endl;
return 1;
}
separate_compilation = source_files.size() > 1;
if( depfile_name ) {
depend_file = fopen(depfile_name, "a");
if(! depend_file) {
@ -940,16 +1002,22 @@ int main(int argc, char*argv[])
switch (generation_flag) {
case GN_VER2012:
lexor_keyword_mask |= GN_KEYWORDS_1800_2012;
// fallthrough
case GN_VER2009:
lexor_keyword_mask |= GN_KEYWORDS_1800_2009;
// fallthrough
case GN_VER2005_SV:
lexor_keyword_mask |= GN_KEYWORDS_1800_2005;
// fallthrough
case GN_VER2005:
lexor_keyword_mask |= GN_KEYWORDS_1364_2005;
// fallthrough
case GN_VER2001:
lexor_keyword_mask |= GN_KEYWORDS_1364_2001_CONFIG;
// fallthrough
case GN_VER2001_NOCONFIG:
lexor_keyword_mask |= GN_KEYWORDS_1364_2001;
// fallthrough
case GN_VER1995:
lexor_keyword_mask |= GN_KEYWORDS_1364_1995;
}
@ -1023,8 +1091,10 @@ int main(int argc, char*argv[])
if (flag_tmp) disable_concatz_generation = strcmp(flag_tmp,"true")==0;
/* Parse the input. Make the pform. */
pform_set_timescale(def_ts_units, def_ts_prec, 0, 0);
int rc = pform_parse(argv[optind]);
int rc = 0;
for (unsigned idx = 0; idx < source_files.size(); idx += 1) {
rc += pform_parse(source_files[idx]);
}
if (pf_path) {
ofstream out (pf_path);
@ -1038,22 +1108,16 @@ int main(int argc, char*argv[])
; cur != disciplines.end() ; ++ cur ) {
pform_dump(out, (*cur).second);
}
out << "PFORM DUMP $ROOT TASKS/FUNCTIONS:" << endl;
for (map<perm_string,PTaskFunc*>::iterator cur = pform_tasks.begin()
; cur != pform_tasks.end() ; ++ cur) {
pform_dump(out, cur->second);
}
out << "PFORM DUMP $ROOT CLASSES:" << endl;
for (map<perm_string,PClass*>::iterator cur = pform_classes.begin()
; cur != pform_classes.end() ; ++ cur) {
pform_dump(out, cur->second);
out << "PFORM DUMP COMPILATION UNITS:" << endl;
for (vector<PPackage*>::iterator pac = pform_units.begin()
; pac != pform_units.end() ; ++ pac) {
pform_dump(out, *pac);
}
out << "PFORM DUMP PACKAGES:" << endl;
for (map<perm_string,PPackage*>::iterator pac = pform_packages.begin()
; pac != pform_packages.end() ; ++ pac) {
pform_dump(out, pac->second);
}
out << "PFORM DUMP MODULES:" << endl;
for (map<perm_string,Module*>::iterator mod = pform_modules.begin()
; mod != pform_modules.end() ; ++ mod ) {
@ -1171,12 +1235,6 @@ int main(int argc, char*argv[])
(*idx).second = 0;
}
for(map<perm_string,data_type_t*>::iterator it = pform_typedefs.begin()
; it != pform_typedefs.end() ; ++it) {
delete (*it).second;
(*it).second = 0;
}
if (verbose_flag) {
if (times_flag) {
times(cycles+2);

27
mingw-cross.txt Normal file
View File

@ -0,0 +1,27 @@
These are instructions for building Icarus Verilog binaries for
Windows using mingw cross compiler tools on Linux.
To start with, you need the mingw64-cross-* packages for your linux
distribution, which gives you the x86_64-w64-mingw32-* commands
installed on your system. Installing the cross environment is outside
the scope of this writeup.
First, configure with this command:
$ ./configure --host=x86_64-w64-mingw32
This generates the Makefiles needed to cross compile everything with
the mingw32 compiler. The configure script will generate the command
name paths, so long as commands line x86_64-w64-mingw32-gcc
et. al. are in your path.
Next, compile with the command:
$ make HOSTCC=cc HOSTCFLAGS=-O
The configure generated the cross compiler flags, but there are a few
bits that need to be compiled with the native compiler. (version.exe
for example is used by the build process but is not installed.) The
MOSTCC= flag on the make command line makes sure the Makefile knows
about the native tool.

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2015 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
@ -101,11 +101,11 @@ uint64_t Design::scale_to_precision(uint64_t val,
return val;
}
NetScope* Design::make_root_scope(perm_string root, bool program_block,
bool is_interface)
NetScope* Design::make_root_scope(perm_string root, NetScope*unit_scope,
bool program_block, bool is_interface)
{
NetScope *root_scope_;
root_scope_ = new NetScope(0, hname_t(root), NetScope::MODULE,
root_scope_ = new NetScope(0, hname_t(root), NetScope::MODULE, unit_scope,
false, program_block, is_interface);
/* This relies on the fact that the basename return value is
permallocated. */
@ -125,31 +125,18 @@ list<NetScope*> Design::find_root_scopes() const
return root_scopes_;
}
NetScope* Design::make_package_scope(perm_string name)
NetScope* Design::make_package_scope(perm_string name, NetScope*unit_scope,
bool is_unit)
{
NetScope*scope;
scope = new NetScope(0, hname_t(name), NetScope::PACKAGE, false, false);
scope = new NetScope(0, hname_t(name), NetScope::PACKAGE, unit_scope,
false, false, false, is_unit);
scope->set_module_name(scope->basename());
packages_[name] = scope;
return scope;
}
void Design::add_class(netclass_t*cl, PClass*pclass)
{
Definitions::add_class(cl);
class_to_pclass_[cl] = pclass;
}
netclass_t* Design::find_class(perm_string name) const
{
map<perm_string,netclass_t*>::const_iterator cur = classes_.find(name);
if (cur != classes_.end())
return cur->second;
return 0;
}
NetScope* Design::find_package(perm_string name) const
{
map<perm_string,NetScope*>::const_iterator cur = packages_.find(name);
@ -170,17 +157,6 @@ list<NetScope*> Design::find_package_scopes() const
return res;
}
list<NetScope*> Design::find_roottask_scopes() const
{
list<NetScope*>res;
for (map<NetScope*,PTaskFunc*>::const_iterator cur = root_tasks_.begin()
; cur != root_tasks_.end() ; ++ cur) {
res.push_back (cur->first);
}
return res;
}
/*
* This method locates a scope in the design, given its rooted
* hierarchical name. Each component of the key is used to scan one
@ -211,25 +187,6 @@ NetScope* Design::find_scope(const std::list<hname_t>&path) const
}
}
for (map<NetScope*,PTaskFunc*>::const_iterator root = root_tasks_.begin()
; root != root_tasks_.end() ; ++ root) {
NetScope*cur = root->first;
if (path.front() != cur->fullname())
continue;
std::list<hname_t> tmp = path;
tmp.pop_front();
while (cur) {
if (tmp.empty()) return cur;
cur = cur->child( tmp.front() );
tmp.pop_front();
}
}
return 0;
}
@ -253,6 +210,49 @@ NetScope* Design::find_scope(const hname_t&path) const
return 0;
}
static bool is_design_unit(NetScope*scope)
{
return (scope->type() == NetScope::MODULE && !scope->nested_module())
|| (scope->type() == NetScope::PACKAGE);
}
static bool is_subroutine(NetScope::TYPE type)
{
return type == NetScope::TASK || type == NetScope::FUNC;
}
/*
* This method locates a scope within another scope, given its relative
* hierarchical name. Each component of the key is used to scan one
* more step down the tree until the name runs out or the search
* fails.
*/
NetScope* Design::find_scope_(NetScope*scope, const std::list<hname_t>&path,
NetScope::TYPE type) const
{
std::list<hname_t> tmp = path;
do {
hname_t key = tmp.front();
/* If we are looking for a module or we are not
* looking at the last path component check for
* a name match (second line). */
if (scope->type() == NetScope::MODULE
&& (type == NetScope::MODULE || tmp.size() > 1)
&& scope->module_name()==key.peek_name()) {
/* Up references may match module name */
} else {
scope = scope->child( key );
if (scope == 0) break;
}
tmp.pop_front();
} while (! tmp.empty());
return scope;
}
/*
* This is a relative lookup of a scope by name. The starting point is
* the scope parameter within which I start looking for the scope. If
@ -266,36 +266,62 @@ NetScope* Design::find_scope(NetScope*scope, const std::list<hname_t>&path,
if (path.empty())
return scope;
for ( ; scope ; scope = scope->parent()) {
// Record the compilation unit scope for use later.
NetScope*unit_scope = scope->unit();
std::list<hname_t> tmp = path;
// First search upwards through the hierarchy.
while (scope) {
NetScope*found_scope = find_scope_(scope, path, type);
if (found_scope)
return found_scope;
NetScope*cur = scope;
do {
hname_t key = tmp.front();
/* If we are looking for a module or we are not
* looking at the last path component check for
* a name match (second line). */
if (cur->type() == NetScope::MODULE
&& (type == NetScope::MODULE || tmp.size() > 1)
&& cur->module_name()==key.peek_name()) {
// Avoid searching the unit scope twice.
if (scope == unit_scope)
unit_scope = 0;
/* Up references may match module name */
// Special case - see IEEE 1800-2012 section 23.8.1.
if (unit_scope && is_design_unit(scope) && is_subroutine(type)) {
found_scope = find_scope_(unit_scope, path, type);
if (found_scope)
return found_scope;
} else {
cur = cur->child( key );
if (cur == 0) break;
}
tmp.pop_front();
} while (! tmp.empty());
unit_scope = 0;
}
if (cur) return cur;
scope = scope->parent();
}
// If we haven't already done so, search the compilation unit scope.
if (unit_scope) {
NetScope*found_scope = find_scope_(unit_scope, path, type);
if (found_scope)
return found_scope;
}
// Last chance. Look for the name starting at the root.
return find_scope(path);
}
/*
* This method locates a scope within another scope, given its relative
* hierarchical name. Each component of the key is used to scan one
* more step down the tree until the name runs out or the search
* fails.
*/
NetScope* Design::find_scope_(NetScope*scope, const hname_t&path,
NetScope::TYPE type) const
{
/* If we are looking for a module or we are not
* looking at the last path component check for
* a name match (second line). */
if ((scope->type() == NetScope::MODULE) && (type == NetScope::MODULE)
&& (scope->module_name() == path.peek_name())) {
/* Up references may match module name */
return scope;
}
return scope->child( path );
}
/*
* This is a relative lookup of a scope by name. The starting point is
* the scope parameter within which I start looking for the scope. If
@ -307,24 +333,36 @@ NetScope* Design::find_scope(NetScope*scope, const hname_t&path,
{
assert(scope);
for ( ; scope ; scope = scope->parent()) {
// Record the compilation unit scope for use later.
NetScope*unit_scope = scope->unit();
NetScope*cur = scope;
// First search upwards through the hierarchy.
while (scope) {
NetScope*found_scope = find_scope_(scope, path, type);
if (found_scope)
return found_scope;
/* If we are looking for a module or we are not
* looking at the last path component check for
* a name match (second line). */
if (cur->type() == NetScope::MODULE
&& (type == NetScope::MODULE)
&& cur->module_name()==path.peek_name()) {
// Avoid searching the unit scope twice.
if (scope == unit_scope)
unit_scope = 0;
/* Up references may match module name */
// Special case - see IEEE 1800-2012 section 23.8.1.
if (unit_scope && is_design_unit(scope) && is_subroutine(type)) {
found_scope = find_scope_(unit_scope, path, type);
if (found_scope)
return found_scope;
} else {
cur = cur->child( path );
unit_scope = 0;
}
if (cur) return cur;
scope = scope->parent();
}
// If we haven't already done so, search the compilation unit scope.
if (unit_scope) {
NetScope*found_scope = find_scope_(unit_scope, path, type);
if (found_scope)
return found_scope;
}
// Last chance. Look for the name starting at the root.
@ -867,11 +905,6 @@ NetScope* Design::find_task(NetScope*scope, const pform_name_t&name)
return 0;
}
void Design::add_root_task(NetScope*tscope, PTaskFunc*tf)
{
root_tasks_[tscope] = tf;
}
void Design::add_node(NetNode*net)
{
assert(net->design_ == 0);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2013 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
@ -28,6 +28,7 @@
NetEvent::NetEvent(perm_string n)
: name_(n)
{
local_flag_ = false;
scope_ = 0;
snext_ = 0;
probes_ = 0;
@ -345,7 +346,7 @@ void NetEvProbe::find_similar_probes(list<NetEvProbe*>&plist)
}
NetEvWait::NetEvWait(NetProc*pr)
: statement_(pr)
: statement_(pr), has_t0_trigger_(false)
{
}
@ -442,3 +443,8 @@ NetProc* NetEvWait::statement()
{
return statement_;
}
const NetProc* NetEvWait::statement() const
{
return statement_;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2016 Stephen Williams (steve@icarus.com)
* Copyright (c) 2012-2018 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
@ -23,6 +23,10 @@
# include <typeinfo>
# include "ivl_assert.h"
#if __cplusplus < 201103L
#define unique_ptr auto_ptr
#endif
using namespace std;
/*
@ -1018,7 +1022,7 @@ NetExpr* NetESignal::evaluate_function(const LineInfo&loc,
NetExpr* NetETernary::evaluate_function(const LineInfo&loc,
map<perm_string,LocalVar>&context_map) const
{
auto_ptr<NetExpr> cval (cond_->evaluate_function(loc, context_map));
unique_ptr<NetExpr> cval (cond_->evaluate_function(loc, context_map));
switch (const_logical(cval.get())) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002-2016 Stephen Williams (steve@icarus.com)
* Copyright (c) 2002-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
@ -27,29 +27,29 @@
# include "netlist.h"
# include "netmisc.h"
NexusSet* NetExpr::nex_input(bool)
NexusSet* NetExpr::nex_input(bool, bool) const
{
cerr << get_fileline()
<< ": internal error: nex_input not implemented: "
<< *this << endl;
return 0;
return new NexusSet;
}
NexusSet* NetProc::nex_input(bool)
NexusSet* NetProc::nex_input(bool, bool) const
{
cerr << get_fileline()
<< ": internal error: NetProc::nex_input not implemented"
<< endl;
return 0;
return new NexusSet;
}
NexusSet* NetEArrayPattern::nex_input(bool rem_out)
NexusSet* NetEArrayPattern::nex_input(bool rem_out, bool search_funcs) const
{
NexusSet*result = new NexusSet;
for (size_t idx = 0 ; idx < items_.size() ; idx += 1) {
if (items_[idx]==0) continue;
NexusSet*tmp = items_[idx]->nex_input(rem_out);
NexusSet*tmp = items_[idx]->nex_input(rem_out, search_funcs);
if (tmp == 0) continue;
result->add(*tmp);
@ -58,32 +58,32 @@ NexusSet* NetEArrayPattern::nex_input(bool rem_out)
return result;
}
NexusSet* NetEBinary::nex_input(bool rem_out)
NexusSet* NetEBinary::nex_input(bool rem_out, bool search_funcs) const
{
NexusSet*result = left_->nex_input(rem_out);
NexusSet*tmp = right_->nex_input(rem_out);
NexusSet*result = left_->nex_input(rem_out, search_funcs);
NexusSet*tmp = right_->nex_input(rem_out, search_funcs);
result->add(*tmp);
delete tmp;
return result;
}
NexusSet* NetEConcat::nex_input(bool rem_out)
NexusSet* NetEConcat::nex_input(bool rem_out, bool search_funcs) const
{
if (parms_[0] == NULL) return NULL;
NexusSet*result = parms_[0]->nex_input(rem_out);
if (parms_[0] == NULL) return new NexusSet;
NexusSet*result = parms_[0]->nex_input(rem_out, search_funcs);
for (unsigned idx = 1 ; idx < parms_.size() ; idx += 1) {
if (parms_[idx] == NULL) {
delete result;
return NULL;
return new NexusSet;
}
NexusSet*tmp = parms_[idx]->nex_input(rem_out);
NexusSet*tmp = parms_[idx]->nex_input(rem_out, search_funcs);
result->add(*tmp);
delete tmp;
}
return result;
}
NexusSet* NetEAccess::nex_input(bool)
NexusSet* NetEAccess::nex_input(bool, bool) const
{
return new NexusSet;
}
@ -91,59 +91,55 @@ NexusSet* NetEAccess::nex_input(bool)
/*
* A constant has not inputs, so always return an empty set.
*/
NexusSet* NetEConst::nex_input(bool)
NexusSet* NetEConst::nex_input(bool, bool) const
{
return new NexusSet;
}
NexusSet* NetECReal::nex_input(bool)
NexusSet* NetECReal::nex_input(bool, bool) const
{
return new NexusSet;
}
NexusSet* NetEEvent::nex_input(bool)
NexusSet* NetEEvent::nex_input(bool, bool) const
{
return new NexusSet;
}
NexusSet* NetELast::nex_input(bool)
NexusSet* NetELast::nex_input(bool, bool) const
{
return new NexusSet;
}
NexusSet* NetENetenum::nex_input(bool)
NexusSet* NetENetenum::nex_input(bool, bool) const
{
return new NexusSet;
}
NexusSet* NetENew::nex_input(bool)
NexusSet* NetENew::nex_input(bool, bool) const
{
return new NexusSet;
}
NexusSet* NetENull::nex_input(bool)
NexusSet* NetENull::nex_input(bool, bool) const
{
return new NexusSet;
}
NexusSet* NetEProperty::nex_input(bool)
NexusSet* NetEProperty::nex_input(bool, bool) const
{
return new NexusSet;
}
NexusSet* NetEScope::nex_input(bool)
NexusSet* NetEScope::nex_input(bool, bool) const
{
return new NexusSet;
}
NexusSet* NetESelect::nex_input(bool rem_out)
NexusSet* NetESelect::nex_input(bool rem_out, bool search_funcs) const
{
NexusSet*result = base_? base_->nex_input(rem_out) : new NexusSet();
NexusSet*tmp = expr_->nex_input(rem_out);
if (tmp == NULL) {
delete result;
return NULL;
}
NexusSet*result = base_? base_->nex_input(rem_out, search_funcs) : new NexusSet();
NexusSet*tmp = expr_->nex_input(rem_out, search_funcs);
result->add(*tmp);
delete tmp;
/* See the comment for NetESignal below. */
@ -157,30 +153,29 @@ NexusSet* NetESelect::nex_input(bool rem_out)
/*
* The $fread, etc. system functions can have NULL arguments.
*/
NexusSet* NetESFunc::nex_input(bool rem_out)
NexusSet* NetESFunc::nex_input(bool rem_out, bool search_funcs) const
{
if (parms_.empty())
return new NexusSet;
NexusSet*result = new NexusSet;
NexusSet*result;
if (parms_[0]) result = parms_[0]->nex_input(rem_out);
else result = new NexusSet;
for (unsigned idx = 1 ; idx < parms_.size() ; idx += 1) {
if (parms_.empty()) return result;
for (unsigned idx = 0 ; idx < parms_.size() ; idx += 1) {
if (parms_[idx]) {
NexusSet*tmp = parms_[idx]->nex_input(rem_out);
NexusSet*tmp = parms_[idx]->nex_input(rem_out, search_funcs);
result->add(*tmp);
delete tmp;
}
}
return result;
}
NexusSet* NetEShallowCopy::nex_input(bool)
NexusSet* NetEShallowCopy::nex_input(bool, bool) const
{
return new NexusSet;
}
NexusSet* NetESignal::nex_input(bool rem_out)
NexusSet* NetESignal::nex_input(bool rem_out, bool search_funcs) const
{
/*
* This is not what I would expect for the various selects (bit,
@ -194,7 +189,7 @@ NexusSet* NetESignal::nex_input(bool rem_out)
/* If we have an array index add it to the sensitivity list. */
if (word_) {
NexusSet*tmp;
tmp = word_->nex_input(rem_out);
tmp = word_->nex_input(rem_out, search_funcs);
result->add(*tmp);
delete tmp;
if (warn_sens_entire_arr) {
@ -209,27 +204,44 @@ NexusSet* NetESignal::nex_input(bool rem_out)
return result;
}
NexusSet* NetETernary::nex_input(bool rem_out)
NexusSet* NetETernary::nex_input(bool rem_out, bool search_funcs) const
{
NexusSet*tmp;
NexusSet*result = cond_->nex_input(rem_out);
NexusSet*result = cond_->nex_input(rem_out, search_funcs);
tmp = true_val_->nex_input(rem_out);
tmp = true_val_->nex_input(rem_out, search_funcs);
result->add(*tmp);
delete tmp;
tmp = false_val_->nex_input(rem_out);
tmp = false_val_->nex_input(rem_out, search_funcs);
result->add(*tmp);
delete tmp;
return result;
}
NexusSet* NetEUFunc::nex_input(bool rem_out)
NexusSet* NetEUFunc::nex_input(bool rem_out, bool search_funcs) const
{
NexusSet*result = new NexusSet;
for (unsigned idx = 0 ; idx < parms_.size() ; idx += 1) {
NexusSet*tmp = parms_[idx]->nex_input(rem_out);
NexusSet*tmp = parms_[idx]->nex_input(rem_out, search_funcs);
result->add(*tmp);
delete tmp;
}
if (search_funcs) {
NetFuncDef*func = func_->func_def();
NexusSet*tmp = func->proc()->nex_input(rem_out, search_funcs);
// Remove the function inputs
NexusSet*in = new NexusSet;
for (unsigned idx = 0 ; idx < func->port_count() ; idx += 1) {
NetNet*net = func->port(idx);
assert(net->pin_count() == 1);
in->add(net->pin(0).nexus(), 0, net->vector_width());
}
tmp->rem(*in);
delete in;
result->add(*tmp);
delete tmp;
}
@ -237,21 +249,28 @@ NexusSet* NetEUFunc::nex_input(bool rem_out)
return result;
}
NexusSet* NetEUnary::nex_input(bool rem_out)
NexusSet* NetEUnary::nex_input(bool rem_out, bool search_funcs) const
{
return expr_->nex_input(rem_out);
return expr_->nex_input(rem_out, search_funcs);
}
NexusSet* NetAssign_::nex_input(bool rem_out)
NexusSet* NetAlloc::nex_input(bool, bool) const
{
return new NexusSet;
}
NexusSet* NetAssign_::nex_input(bool rem_out, bool search_funcs) const
{
assert(! nest_);
NexusSet*result = new NexusSet;
if (word_) {
NexusSet*tmp = word_->nex_input(rem_out);
NexusSet*tmp = word_->nex_input(rem_out, search_funcs);
result->add(*tmp);
delete tmp;
}
if (base_) {
NexusSet*tmp = base_->nex_input(rem_out);
NexusSet*tmp = base_->nex_input(rem_out, search_funcs);
result->add(*tmp);
delete tmp;
}
@ -259,15 +278,21 @@ NexusSet* NetAssign_::nex_input(bool rem_out)
return result;
}
NexusSet* NetAssignBase::nex_input(bool rem_out)
NexusSet* NetAssignBase::nex_input(bool rem_out, bool search_funcs) const
{
NexusSet*result = rval_->nex_input(rem_out);
NexusSet*result = new NexusSet;
// For the deassign and release statements there is no R-value.
if (rval_) {
NexusSet*tmp = rval_->nex_input(rem_out, search_funcs);
result->add(*tmp);
delete tmp;
}
/* It is possible that the lval_ can have nex_input values. In
particular, index expressions are statement inputs as well,
so should be addressed here. */
for (NetAssign_*cur = lval_ ; cur ; cur = cur->more) {
NexusSet*tmp = cur->nex_input(rem_out);
NexusSet*tmp = cur->nex_input(rem_out, search_funcs);
result->add(*tmp);
delete tmp;
}
@ -292,16 +317,15 @@ NexusSet* NetAssignBase::nex_input(bool rem_out)
* In this example, "t" should not be in the input set because it is
* used by the sequence as a temporary value.
*/
NexusSet* NetBlock::nex_input(bool rem_out)
NexusSet* NetBlock::nex_input(bool rem_out, bool search_funcs) const
{
if (last_ == 0)
return new NexusSet;
if (last_ == 0) return new NexusSet;
if (type_ != SEQU) {
if (! search_funcs && (type_ != SEQU)) {
cerr << get_fileline() << ": internal error: Sorry, "
<< "I don't know how to synthesize fork/join blocks."
<< endl;
return 0;
return new NexusSet;
}
NetProc*cur = last_->next_;
@ -312,10 +336,10 @@ NexusSet* NetBlock::nex_input(bool rem_out)
do {
/* Get the inputs for the current statement. */
NexusSet*tmp = cur->nex_input(rem_out);
NexusSet*tmp = cur->nex_input(rem_out, search_funcs);
/* Add the current input set to the accumulated input set. */
if (tmp != 0) result->add(*tmp);
result->add(*tmp);
delete tmp;
/* Add the current outputs to the accumulated output set if
@ -339,11 +363,9 @@ NexusSet* NetBlock::nex_input(bool rem_out)
* the inputs to all the guards, and the inputs to all the guarded
* statements.
*/
NexusSet* NetCase::nex_input(bool rem_out)
NexusSet* NetCase::nex_input(bool rem_out, bool search_funcs) const
{
NexusSet*result = expr_->nex_input(rem_out);
if (result == 0)
return 0;
NexusSet*result = expr_->nex_input(rem_out, search_funcs);
for (size_t idx = 0 ; idx < items_.size() ; idx += 1) {
@ -351,8 +373,7 @@ NexusSet* NetCase::nex_input(bool rem_out)
if (items_[idx].statement == 0)
continue;
NexusSet*tmp = items_[idx].statement->nex_input(rem_out);
assert(tmp);
NexusSet*tmp = items_[idx].statement->nex_input(rem_out, search_funcs);
result->add(*tmp);
delete tmp;
@ -360,8 +381,7 @@ NexusSet* NetCase::nex_input(bool rem_out)
case is special and is identified by a null
guard. The default guard obviously has no input. */
if (items_[idx].guard) {
tmp = items_[idx].guard->nex_input(rem_out);
assert(tmp);
tmp = items_[idx].guard->nex_input(rem_out, search_funcs);
result->add(*tmp);
delete tmp;
}
@ -370,24 +390,18 @@ NexusSet* NetCase::nex_input(bool rem_out)
return result;
}
NexusSet* NetCAssign::nex_input(bool)
NexusSet* NetCondit::nex_input(bool rem_out, bool search_funcs) const
{
cerr << get_fileline() << ": internal warning: NetCAssign::nex_input()"
<< " not implemented." << endl;
return new NexusSet;
}
NexusSet*result = expr_->nex_input(rem_out, search_funcs);
NexusSet* NetCondit::nex_input(bool rem_out)
{
NexusSet*result = expr_->nex_input(rem_out);
if (if_ != 0) {
NexusSet*tmp = if_->nex_input(rem_out);
NexusSet*tmp = if_->nex_input(rem_out, search_funcs);
result->add(*tmp);
delete tmp;
}
if (else_ != 0) {
NexusSet*tmp = else_->nex_input(rem_out);
NexusSet*tmp = else_->nex_input(rem_out, search_funcs);
result->add(*tmp);
delete tmp;
}
@ -395,51 +409,85 @@ NexusSet* NetCondit::nex_input(bool rem_out)
return result;
}
NexusSet* NetDoWhile::nex_input(bool rem_out)
NexusSet* NetDisable::nex_input(bool, bool) const
{
NexusSet*result = proc_->nex_input(rem_out);
NexusSet*tmp = cond_->nex_input(rem_out);
result->add(*tmp);
delete tmp;
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()"
<< " not implemented." << endl;
return new NexusSet;
}
NexusSet* NetForLoop::nex_input(bool rem_out)
NexusSet* NetDoWhile::nex_input(bool rem_out, bool search_funcs) const
{
NexusSet*result = init_expr_->nex_input(rem_out);
NexusSet*result = cond_->nex_input(rem_out, search_funcs);
NexusSet*tmp = condition_->nex_input(rem_out);
result->add(*tmp);
delete tmp;
if (proc_) {
NexusSet*tmp = proc_->nex_input(rem_out, search_funcs);
result->add(*tmp);
delete tmp;
}
tmp = statement_->nex_input(rem_out);
result->add(*tmp);
delete tmp;
return result;
}
tmp = step_statement_->nex_input(rem_out);
result->add(*tmp);
delete tmp;
NexusSet* NetEvTrig::nex_input(bool, bool) const
{
return new NexusSet;
}
NexusSet* NetEvWait::nex_input(bool rem_out, bool search_funcs) const
{
NexusSet*result = new NexusSet;
if (statement_) {
NexusSet*tmp = statement_->nex_input(rem_out, search_funcs);
result->add(*tmp);
delete tmp;
}
return result;
}
NexusSet* NetForever::nex_input(bool rem_out, bool search_funcs) const
{
NexusSet*result = new NexusSet;
if (statement_) {
NexusSet*tmp = statement_->nex_input(rem_out, search_funcs);
result->add(*tmp);
delete tmp;
}
return result;
}
NexusSet* NetForLoop::nex_input(bool rem_out, bool search_funcs) const
{
NexusSet*result = new NexusSet;
if (init_expr_) {
NexusSet*tmp = init_expr_->nex_input(rem_out, search_funcs);
result->add(*tmp);
delete tmp;
}
if (condition_) {
NexusSet*tmp = condition_->nex_input(rem_out, search_funcs);
result->add(*tmp);
delete tmp;
}
if (step_statement_) {
NexusSet*tmp = step_statement_->nex_input(rem_out, search_funcs);
result->add(*tmp);
delete tmp;
}
if (statement_) {
NexusSet*tmp = statement_->nex_input(rem_out, search_funcs);
result->add(*tmp);
delete tmp;
}
if (gn_shared_loop_index_flag) {
tmp = new NexusSet();
NexusSet*tmp = new NexusSet();
for (unsigned idx = 0 ; idx < index_->pin_count() ; idx += 1)
tmp->add(index_->pin(idx).nexus(), 0, index_->vector_width());
@ -450,10 +498,9 @@ NexusSet* NetForLoop::nex_input(bool rem_out)
return result;
}
NexusSet* NetForever::nex_input(bool rem_out)
NexusSet* NetFree::nex_input(bool, bool) const
{
NexusSet*result = statement_->nex_input(rem_out);
return result;
return new NexusSet;
}
/*
@ -465,36 +512,44 @@ NexusSet* NetForever::nex_input(bool rem_out)
* include the input set of the <expr> because it does not affect the
* result. The statement can be omitted.
*/
NexusSet* NetPDelay::nex_input(bool rem_out)
NexusSet* NetPDelay::nex_input(bool rem_out, bool search_funcs) const
{
if (statement_ == 0) return 0;
NexusSet*result = statement_->nex_input(rem_out);
NexusSet*result = new NexusSet;
if (statement_) {
NexusSet*tmp = statement_->nex_input(rem_out, search_funcs);
result->add(*tmp);
delete tmp;
}
return result;
}
NexusSet* NetRepeat::nex_input(bool rem_out)
NexusSet* NetRepeat::nex_input(bool rem_out, bool search_funcs) const
{
NexusSet*result = statement_->nex_input(rem_out);
NexusSet*tmp = expr_->nex_input(rem_out);
result->add(*tmp);
delete tmp;
NexusSet*result = expr_->nex_input(rem_out, search_funcs);
if (statement_) {
NexusSet*tmp = statement_->nex_input(rem_out, search_funcs);
result->add(*tmp);
delete tmp;
}
return result;
}
/*
* The $display, etc. system tasks can have NULL arguments.
*/
NexusSet* NetSTask::nex_input(bool rem_out)
NexusSet* NetSTask::nex_input(bool rem_out, bool search_funcs) const
{
if (parms_.empty())
return new NexusSet;
NexusSet*result = new NexusSet;
NexusSet*result;
if (parms_[0]) result = parms_[0]->nex_input(rem_out);
else result = new NexusSet;
for (unsigned idx = 1 ; idx < parms_.size() ; idx += 1) {
if (parms_.empty()) return result;
for (unsigned idx = 0 ; idx < parms_.size() ; idx += 1) {
if (parms_[idx]) {
NexusSet*tmp = parms_[idx]->nex_input(rem_out);
NexusSet*tmp = parms_[idx]->nex_input(rem_out, search_funcs);
result->add(*tmp);
delete tmp;
}
@ -508,16 +563,20 @@ NexusSet* NetSTask::nex_input(bool rem_out)
* parameters to consider, because the compiler already removed them
* and converted them to blocking assignments.
*/
NexusSet* NetUTask::nex_input(bool)
NexusSet* NetUTask::nex_input(bool, bool) const
{
return new NexusSet;
}
NexusSet* NetWhile::nex_input(bool rem_out)
NexusSet* NetWhile::nex_input(bool rem_out, bool search_funcs) const
{
NexusSet*result = proc_->nex_input(rem_out);
NexusSet*tmp = cond_->nex_input(rem_out);
result->add(*tmp);
delete tmp;
NexusSet*result = cond_->nex_input(rem_out, search_funcs);
if (proc_) {
NexusSet*tmp = proc_->nex_input(rem_out, search_funcs);
result->add(*tmp);
delete tmp;
}
return result;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002-2013 Stephen Williams (steve@icarus.com)
* Copyright (c) 2002-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
@ -36,8 +36,13 @@ void NetProc::nex_output(NexusSet&)
<< endl;
}
void NetAlloc::nex_output(NexusSet&)
{
}
void NetAssign_::nex_output(NexusSet&out)
{
assert(! nest_);
assert(sig_);
unsigned use_word = 0;
unsigned use_base = 0;
@ -89,8 +94,7 @@ void NetAssignBase::nex_output(NexusSet&out)
void NetBlock::nex_output(NexusSet&out)
{
if (last_ == 0)
return;
if (last_ == 0) return;
NetProc*cur = last_;
do {
@ -104,10 +108,8 @@ void NetCase::nex_output(NexusSet&out)
for (size_t idx = 0 ; idx < items_.size() ; idx += 1) {
// Empty statements clearly have no output.
if (items_[idx].statement == 0)
continue;
if (items_[idx].statement == 0) continue;
assert(items_[idx].statement);
items_[idx].statement->nex_output(out);
}
@ -115,22 +117,31 @@ void NetCase::nex_output(NexusSet&out)
void NetCondit::nex_output(NexusSet&out)
{
if (if_ != 0)
if_->nex_output(out);
if (else_ != 0)
else_->nex_output(out);
if (if_) if_->nex_output(out);
if (else_) else_->nex_output(out);
}
void NetDisable::nex_output(NexusSet&)
{
}
void NetDoWhile::nex_output(NexusSet&out)
{
if (proc_ != 0)
proc_->nex_output(out);
if (proc_) proc_->nex_output(out);
}
void NetEvTrig::nex_output(NexusSet&)
{
}
void NetEvWait::nex_output(NexusSet&out)
{
assert(statement_);
statement_->nex_output(out);
if (statement_) statement_->nex_output(out);
}
void NetForever::nex_output(NexusSet&out)
{
if (statement_) statement_->nex_output(out);
}
void NetForLoop::nex_output(NexusSet&out)
@ -138,11 +149,20 @@ void NetForLoop::nex_output(NexusSet&out)
if (statement_) statement_->nex_output(out);
}
void NetFree::nex_output(NexusSet&)
{
}
void NetPDelay::nex_output(NexusSet&out)
{
if (statement_) statement_->nex_output(out);
}
void NetRepeat::nex_output(NexusSet&out)
{
if (statement_) statement_->nex_output(out);
}
/*
* For the purposes of synthesis, system task calls have no output at
* all. This is OK because most system tasks are not synthesizable in
@ -163,6 +183,5 @@ void NetUTask::nex_output(NexusSet&)
void NetWhile::nex_output(NexusSet&out)
{
if (proc_ != 0)
proc_->nex_output(out);
if (proc_) proc_->nex_output(out);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2016 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2017 Stephen Williams (steve@icarus.com)
* Copyright (c) 2016 CERN Michele Castellana (michele.castellana@cern.ch)
*
* This source code is free software; you can redistribute it
@ -112,10 +112,10 @@ void Definitions::add_class(netclass_t*net_class)
* in question.
*/
NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t, bool nest,
bool program, bool interface)
NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t, NetScope*in_unit,
bool nest, bool program, bool interface, bool compilation_unit)
: type_(t), name_(n), nested_module_(nest), program_block_(program),
is_interface_(interface), up_(up)
is_interface_(interface), is_unit_(compilation_unit), unit_(in_unit), up_(up)
{
events_ = 0;
lcounter_ = 0;
@ -124,6 +124,9 @@ NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t, bool nest,
calls_stask_ = false;
in_final_ = false;
if (compilation_unit)
unit_ = this;
if (up) {
assert(t!=CLASS);
need_const_func_ = up->need_const_func_;
@ -133,6 +136,8 @@ NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t, bool nest,
time_from_timescale_ = up->time_from_timescale();
// Need to check for duplicate names?
up_->children_[name_] = this;
if (unit_ == 0)
unit_ = up_->unit_;
} else {
need_const_func_ = false;
is_const_func_ = false;
@ -210,6 +215,8 @@ const netenum_t*NetScope::find_enumeration_for_name(perm_string name)
NetEConstEnum*tmp = cur_scope->enum_names_[name];
if (tmp) break;
cur_scope = cur_scope->parent();
if (cur_scope == 0)
cur_scope = unit_;
}
assert(cur_scope);
@ -304,16 +311,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)
@ -364,12 +371,7 @@ const NetExpr* NetScope::get_parameter(Design*des,
msb = 0;
lsb = 0;
const NetExpr*tmp = enumeration_expr(key);
if (tmp) return tmp;
tmp = des->enumeration_expr(key);
if (tmp) return tmp;
return 0;
return tmp;
}
NetScope::param_ref_t NetScope::find_parameter(perm_string key)
@ -386,11 +388,6 @@ NetScope::param_ref_t NetScope::find_parameter(perm_string key)
return idx;
}
NetScope::TYPE NetScope::type() const
{
return type_;
}
void NetScope::print_type(ostream&stream) const
{
switch (type_) {
@ -657,15 +654,11 @@ netclass_t*NetScope::find_class(perm_string name)
if (type_==CLASS && name_==hname_t(name))
return class_def_;
// Look for the class that directly within this scope.
// Look for the class directly within this scope.
map<perm_string,netclass_t*>::const_iterator cur = classes_.find(name);
if (cur != classes_.end())
return cur->second;
// If this is a module scope, then look no further.
if (type_==MODULE)
return 0;
if (up_==0 && type_==CLASS) {
assert(class_def_);
@ -673,12 +666,16 @@ netclass_t*NetScope::find_class(perm_string name)
return def_parent->find_class(name);
}
// If there is no further to look, ...
if (up_ == 0)
return 0;
// Try looking up for the class.
return up_->find_class(name);
if (up_!=0 && type_!=MODULE)
return up_->find_class(name);
// Try the compilation unit.
if (unit_ != 0)
return unit_->find_class(name);
// Nowhere left to try...
return 0;
}
/*

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2014 Stephen Williams (steve@icarus.com)
* Copyright (c) 2012-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
@ -165,7 +165,8 @@ bool netclass_t::test_for_missing_initializers() const
NetScope*netclass_t::method_from_name(perm_string name) const
{
NetScope*task = class_scope_->child( hname_t(name) );
if (task == 0) return 0;
if ((task == 0) && super_)
task = super_->method_from_name(name);
return task;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2016 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-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
@ -24,6 +24,7 @@
# include <typeinfo>
# include <cstdlib>
# include <climits>
# include <cstring>
# include "compiler.h"
# include "netlist.h"
# include "netmisc.h"
@ -2768,7 +2769,7 @@ static DelayType delay_type_from_expr(const NetExpr*expr)
* The looping structures can use the same basic code so put it here
* instead of duplicating it for each one (repeat and while).
*/
static DelayType get_loop_delay_type(const NetExpr*expr, const NetProc*proc)
static DelayType get_loop_delay_type(const NetExpr*expr, const NetProc*proc, bool print_delay)
{
DelayType result;
@ -2779,12 +2780,20 @@ static DelayType get_loop_delay_type(const NetExpr*expr, const NetProc*proc)
break;
/* We have a constant true expression so the body always runs. */
case DEFINITE_DELAY:
result = proc->delay_type();
if (proc) {
result = proc->delay_type(print_delay);
} else {
result = NO_DELAY;
}
break;
/* We don't know if the body will run so reduce a DEFINITE_DELAY
* to a POSSIBLE_DELAY. All other stay the same. */
case POSSIBLE_DELAY:
result = combine_delays(NO_DELAY, proc->delay_type());
if (proc) {
result = combine_delays(NO_DELAY, proc->delay_type(print_delay));
} else {
result = NO_DELAY;
}
break;
/* This should never happen since delay_type_from_expr() only
* returns three different values. */
@ -2797,25 +2806,40 @@ static DelayType get_loop_delay_type(const NetExpr*expr, const NetProc*proc)
}
/* The default object does not have any delay. */
DelayType NetProc::delay_type() const
DelayType NetProc::delay_type(bool /* print_delay */ ) const
{
return NO_DELAY;
}
DelayType NetBlock::delay_type() const
DelayType NetBlock::delay_type(bool print_delay) const
{
DelayType result = NO_DELAY;
// A join_none has no delay.
if (type() == PARA_JOIN_NONE) return NO_DELAY;
for (const NetProc*cur = proc_first(); cur; cur = proc_next(cur)) {
DelayType dt = cur->delay_type();
if (dt > result) result = dt;
if (dt == DEFINITE_DELAY) break;
DelayType result;
// A join_any has the minimum delay.
if (type() == PARA_JOIN_ANY) {
result = DEFINITE_DELAY;
for (const NetProc*cur = proc_first(); cur; cur = proc_next(cur)) {
DelayType dt = cur->delay_type(print_delay);
if (dt < result) result = dt;
if ((dt == NO_DELAY) && !print_delay) break;
}
// A begin or join has the maximum delay.
} else {
result = NO_DELAY;
for (const NetProc*cur = proc_first(); cur; cur = proc_next(cur)) {
DelayType dt = cur->delay_type(print_delay);
if (dt > result) result = dt;
if ((dt == DEFINITE_DELAY) && !print_delay) break;
}
}
return result;
}
DelayType NetCase::delay_type() const
DelayType NetCase::delay_type(bool print_delay) const
{
DelayType result = NO_DELAY;
bool def_stmt = false;
@ -2823,7 +2847,7 @@ 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;
DelayType dt = stat(idx) ? stat(idx)->delay_type(print_delay) : NO_DELAY;
if (idx == 0) {
result = dt;
} else {
@ -2831,6 +2855,7 @@ DelayType NetCase::delay_type() const
}
}
// FIXME: If all the cases are covered (e.g. an enum) then this is not true.
/* If we don't have a default statement we don't know for sure
* that we have a delay. */
if (!def_stmt) result = combine_delays(NO_DELAY, result);
@ -2838,74 +2863,636 @@ DelayType NetCase::delay_type() const
return result;
}
DelayType NetCondit::delay_type() const
DelayType NetCondit::delay_type(bool print_delay) const
{
DelayType if_type = if_ ? if_->delay_type() : NO_DELAY;
DelayType el_type = else_? else_->delay_type() : NO_DELAY;
DelayType if_type = if_ ? if_->delay_type(print_delay) : NO_DELAY;
DelayType el_type = else_? else_->delay_type(print_delay) : NO_DELAY;
return combine_delays(if_type, el_type);
}
/*
* A do/while will execute the body at least once.
*/
DelayType NetDoWhile::delay_type() const
DelayType NetDoWhile::delay_type(bool print_delay) const
{
ivl_assert(*this, proc_);
return proc_->delay_type();
if (proc_) return proc_->delay_type(print_delay);
return ZERO_DELAY;
}
DelayType NetEvWait::delay_type() const
DelayType NetEvWait::delay_type(bool print_delay) const
{
if (print_delay) {
cerr << get_fileline() << ": error: an event control is not allowed "
"in an always_comb, always_ff or always_latch process."
<< endl;
}
return DEFINITE_DELAY;
}
DelayType NetForever::delay_type() const
DelayType NetForever::delay_type(bool print_delay) const
{
ivl_assert(*this, statement_);
return statement_->delay_type();
if (statement_) return statement_->delay_type(print_delay);
return ZERO_DELAY;
}
DelayType NetForLoop::delay_type() const
DelayType NetForLoop::delay_type(bool print_delay) const
{
ivl_assert(*this, statement_);
return get_loop_delay_type(condition_, statement_);
return get_loop_delay_type(condition_, statement_, print_delay);
}
DelayType NetPDelay::delay_type() const
DelayType NetPDelay::delay_type(bool print_delay) const
{
if (print_delay) {
cerr << get_fileline() << ": error: a blocking delay is not allowed "
"in an always_comb, always_ff or always_latch process."
<< endl;
}
if (expr_) {
return delay_type_from_expr(expr_);
} else {
if (delay() > 0) {
return DEFINITE_DELAY;
if (statement_) {
return combine_delays(delay_type_from_expr(expr_),
statement_->delay_type(print_delay));
} else {
if (statement_) {
return statement_->delay_type();
} else {
return NO_DELAY;
}
return delay_type_from_expr(expr_);
}
}
if (delay() > 0) return DEFINITE_DELAY;
if (statement_) {
return combine_delays(ZERO_DELAY,
statement_->delay_type(print_delay));
} else {
return ZERO_DELAY;
}
}
DelayType NetRepeat::delay_type(bool print_delay) const
{
return get_loop_delay_type(expr_, statement_, print_delay);
}
DelayType NetTaskDef::delay_type(bool print_delay) const
{
if (proc_) {
return proc_->delay_type(print_delay);
} else {
return NO_DELAY;
}
}
DelayType NetUTask::delay_type(bool print_delay) const
{
return task()->task_def()->delay_type(print_delay);
}
static bool do_expr_event_match(const NetExpr*expr, const NetEvWait*evwt)
{
// The event wait should only have a single event.
if (evwt->nevents() != 1) return false;
// The event should have a single probe.
const NetEvent *evt = evwt->event(0);
if (evt->nprobe() != 1) return false;
// The probe should be for any edge.
const NetEvProbe *prb = evt->probe(0);
if (prb->edge() != NetEvProbe::ANYEDGE) return false;
// Create a NexusSet from the event probe signals.
NexusSet *ns_evwt = new NexusSet;
for (unsigned idx =0; idx < prb->pin_count(); idx += 1) {
if (! prb->pin(idx).is_linked()) {
delete ns_evwt;
return false;
}
// Casting away const is safe since this nexus set is only being read.
ns_evwt->add(const_cast<Nexus*> (prb->pin(idx).nexus()),
0, prb->pin(idx).nexus()->vector_width());
}
// Get the NexusSet for the expression.
NexusSet *ns_expr = expr->nex_input();
// Make sure the event and expression NexusSets match exactly.
if (ns_evwt->size() != ns_expr->size()) {
delete ns_evwt;
delete ns_expr;
return false;
}
ns_expr->rem(*ns_evwt);
delete ns_evwt;
if (ns_expr->size() != 0) {
delete ns_expr;
return false;
}
delete ns_expr;
return true;
}
static bool while_is_wait(const NetExpr*expr, const NetProc*stmt)
{
if (const NetEvWait*evwt = dynamic_cast<const NetEvWait*>(stmt)) {
if (evwt->statement()) return false;
const NetEBComp*cond = dynamic_cast<const NetEBComp*>(expr);
if (! cond) return false;
if (cond->op() != 'N') return false;
const NetEConst*cval = dynamic_cast<const NetEConst*>(cond->right());
if (! cval) return false;
const verinum val = cval->value();
if (val.len() != 1) return false;
if (val.get(0) != verinum::V1) return false;
if (! do_expr_event_match(cond->left(), evwt)) return false;
if (evwt->get_lineno() != cond->get_lineno()) return false;
if (evwt->get_file() != cond->get_file()) return false;
return true;
}
return false;
}
DelayType NetWhile::delay_type(bool print_delay) const
{
// If the wait was a constant value the compiler already removed it
// so we know we can only have a possible delay.
if (while_is_wait(cond_, proc_)) {
if (print_delay) {
cerr << get_fileline() << ": error: a wait statement is "
"not allowed in an "
"always_comb, always_ff or always_latch process."
<< endl;
}
return POSSIBLE_DELAY;
}
return get_loop_delay_type(cond_, proc_, print_delay);
}
/*
* These are the check_synth() functions. They are used to print
* a warning if the item is not synthesizable.
*/
static const char * get_process_type_as_string(ivl_process_type_t pr_type)
{
switch (pr_type) {
case IVL_PR_ALWAYS_COMB:
return "in an always_comb process.";
break;
case IVL_PR_ALWAYS_FF:
return "in an always_ff process.";
break;
case IVL_PR_ALWAYS_LATCH:
return "in an always_latch process.";
break;
default:
assert(0);
return 0;
}
}
static void print_synth_warning(const NetProc *net_proc, const char *name,
ivl_process_type_t pr_type)
{
cerr << net_proc->get_fileline() << ": warning: " << name
<< " statement cannot be synthesized "
<< get_process_type_as_string(pr_type) << endl;
}
static void check_if_logic_l_value(const NetAssignBase *base,
ivl_process_type_t pr_type)
{
if (base->l_val_count() != 1) return;
const NetAssign_*lval = base->l_val(0);
if (! lval) return;
NetNet*sig = lval->sig();
if (! sig) return;
if ((sig->data_type() != IVL_VT_BOOL) &&
(sig->data_type() != IVL_VT_LOGIC)) {
cerr << base->get_fileline() << ": warning: Assinging to a "
"non-integral variable ("<< sig->name()
<< ") cannot be synthesized "
<< get_process_type_as_string(pr_type) << endl;
}
}
/* By default elements can be synthesized or ignored. */
bool NetProc::check_synth(ivl_process_type_t /* pr_type */,
const NetScope* /* scope */ ) const
{
return false;
}
// FIXME: User function calls still need to be checked (NetEUFunc).
// : Non-constant system functions need a warning (NetESFunc).
// : Constant functions should already be elaborated.
/* By default assign elements can be synthesized. */
bool NetAssignBase::check_synth(ivl_process_type_t /* pr_type */,
const NetScope* /* scope */ ) const
{
return false;
}
bool NetAssign::check_synth(ivl_process_type_t pr_type,
const NetScope* /* scope */ ) const
{
check_if_logic_l_value(this, pr_type);
// FIXME: Check that ff/latch only use this for internal signals.
return false;
}
bool NetAssignNB::check_synth(ivl_process_type_t pr_type,
const NetScope* /* scope */ ) const
{
bool result = false;
if (pr_type == IVL_PR_ALWAYS_COMB) {
cerr << get_fileline() << ": warning: A non-blocking assignment "
"should not be used in an always_comb process." << endl;
}
if (event_) {
cerr << get_fileline() << ": error: A non-blocking assignment "
"cannot be synthesized with an event control "
<< get_process_type_as_string(pr_type) << endl;
result = true;
}
check_if_logic_l_value(this, pr_type);
return result;
}
bool NetBlock::check_synth(ivl_process_type_t pr_type,
const NetScope* scope) const
{
bool result = false;
// Only a begin/end can be synthesized.
if (type() != SEQU) {
cerr << get_fileline() << ": error: A fork/";
switch (type()) {
case PARA:
cerr << "join";
break;
case PARA_JOIN_ANY:
cerr << "join_any";
break;
case PARA_JOIN_NONE:
cerr << "join_none";
break;
default:
assert(0);
}
cerr << " statement cannot be synthesized "
<< get_process_type_as_string(pr_type) << endl;
result = true;
}
const NetScope*save_scope = scope;
if (subscope()) scope = subscope();
if (scope != save_scope) {
result |= scope->check_synth(pr_type, scope);
}
for (const NetProc*cur = proc_first(); cur; cur = proc_next(cur)) {
result |= cur->check_synth(pr_type, scope);
}
scope = save_scope;
return result;
}
bool NetCase::check_synth(ivl_process_type_t pr_type,
const NetScope* scope) const
{
bool result = false;
for (unsigned idx = 0; idx < nitems(); idx += 1) {
if (stat(idx)) result |= stat(idx)->check_synth(pr_type, scope);
}
// FIXME: Check for ff/latch/comb structures.
return result;
}
bool NetCAssign::check_synth(ivl_process_type_t pr_type,
const NetScope* /* scope */ ) const
{
print_synth_warning(this, "A procedural assign", pr_type);
return false;
}
bool NetCondit::check_synth(ivl_process_type_t pr_type,
const NetScope* scope) const
{
bool result = false;
if (if_) result |= if_->check_synth(pr_type, scope);
if (else_) result |= else_->check_synth(pr_type, scope);
// FIXME: Check for ff/latch/comb structures.
return result;
}
bool NetDeassign::check_synth(ivl_process_type_t pr_type,
const NetScope* /* scope */ ) const
{
print_synth_warning(this, "A procedural deassign", pr_type);
return false;
}
bool NetDisable::check_synth(ivl_process_type_t pr_type,
const NetScope* scope) const
{
while (scope) {
if (scope != target_) scope = scope->parent();
else break;
}
if (! scope) {
cerr << get_fileline() << ": warning: A disable statement can "
"only be synthesized when disabling an enclosing block "
<< get_process_type_as_string(pr_type) << endl;
}
return false;
}
bool NetDoWhile::check_synth(ivl_process_type_t pr_type,
const NetScope* scope) const
{
bool result = false;
print_synth_warning(this, "A do/while", pr_type);
if (proc_) result |= proc_->check_synth(pr_type, scope);
return result;
}
bool NetEvTrig::check_synth(ivl_process_type_t pr_type,
const NetScope* /* scope */ ) const
{
print_synth_warning(this, "An event trigger", pr_type);
return false;
}
// The delay check above has already marked this as an error.
bool NetEvWait::check_synth(ivl_process_type_t pr_type,
const NetScope* scope) const
{
bool result = false;
if (statement_) result |= statement_->check_synth(pr_type, scope);
return result;
}
bool NetForce::check_synth(ivl_process_type_t pr_type,
const NetScope* /* scope */ ) const
{
print_synth_warning(this, "A force", pr_type);
return false;
}
bool NetForever::check_synth(ivl_process_type_t pr_type,
const NetScope* scope) const
{
bool result = false;
print_synth_warning(this, "A forever", pr_type);
if (statement_) result |= statement_->check_synth(pr_type, scope);
return result;
}
/*
* A bunch of private routines to verify that a for loop has the correct
* structure for synthesis.
*/
static void print_for_idx_warning(const NetProc*proc, const char*check,
ivl_process_type_t pr_type, NetNet*idx)
{
cerr << proc->get_fileline() << ": warning: A for statement must use "
"the index (" << idx->name() << ") in the " << check
<< " expression to be synthesized "
<< get_process_type_as_string(pr_type) << endl;
}
static void check_for_const_synth(const NetExpr*expr, const NetProc*proc,
const char*str, ivl_process_type_t pr_type)
{
if (! dynamic_cast<const NetEConst*>(expr)) {
cerr << proc-> get_fileline() << ": warning: A for "
"statement must " << str
<< " value to be synthesized "
<< get_process_type_as_string(pr_type) << endl;
}
}
static void check_for_bin_synth(const NetExpr*left,const NetExpr*right,
const char*str, const char*check,
const NetProc*proc,
ivl_process_type_t pr_type, NetNet*index)
{
const NetESignal*lsig = dynamic_cast<const NetESignal*>(left);
const NetESignal*rsig = dynamic_cast<const NetESignal*>(right);
if (lsig && (lsig->sig() == index)) {
check_for_const_synth(right, proc, str, pr_type);
} else if (rsig && (rsig->sig() == index)) {
check_for_const_synth(left, proc, str, pr_type);
} else {
print_for_idx_warning(proc, check, pr_type, index);
}
}
static void print_for_step_warning(const NetProc*proc,
ivl_process_type_t pr_type)
{
cerr << proc->get_fileline() << ": warning: A for statement step must "
"be a simple assignment statement to be synthesized "
<< get_process_type_as_string(pr_type) << endl;
}
static void print_for_step_warning(const NetProc*proc,
ivl_process_type_t pr_type, NetNet*idx)
{
cerr << proc->get_fileline() << ": warning: A for statement step must "
"be an assignment to the index variable ("
<< idx->name() << ") to be synthesized "
<< get_process_type_as_string(pr_type) << endl;
}
static void check_for_bstep_synth(const NetExpr*expr, const NetProc*proc,
ivl_process_type_t pr_type, NetNet*index)
{
if (const NetECast*tmp = dynamic_cast<const NetECast*>(expr)) {
expr = tmp->expr();
}
if (const NetEBAdd*tmp = dynamic_cast<const NetEBAdd*>(expr)) {
check_for_bin_synth(tmp->left(), tmp->right(),
"change by a constant", "step", proc, pr_type,
index);
} else {
cerr << proc->get_fileline() << ": warning: A for statement "
"step must be a simple binary +/- "
"to be synthesized "
<< get_process_type_as_string(pr_type) << endl;
}
}
static void check_for_step_synth(const NetAssign*assign, const NetProc*proc,
ivl_process_type_t pr_type, NetNet*index)
{
if (assign->l_val_count() != 1) {
print_for_step_warning(proc, pr_type);
} else if (assign->l_val(0)->sig() != index) {
print_for_step_warning(proc, pr_type, index);
} else {
switch (assign->assign_operator()) {
case '+':
case '-':
check_for_const_synth(assign->rval(), proc,
"have a constant step", pr_type);
break;
case 0:
check_for_bstep_synth(assign->rval(), proc, pr_type, index);
break;
default:
cerr << proc->get_fileline() << ": warning: A for statement "
"step does not support operator '"
<< assign->assign_operator()
<< "' it must be +/- to be synthesized "
<< get_process_type_as_string(pr_type) << endl;
break;
}
}
}
DelayType NetRepeat::delay_type() const
bool NetForLoop::check_synth(ivl_process_type_t pr_type,
const NetScope* scope) const
{
ivl_assert(*this, statement_);
return get_loop_delay_type(expr_, statement_);
bool result = false;
// FIXME: What about an enum (NetEConstEnum)?
if (! dynamic_cast<const NetEConst*>(init_expr_)) {
cerr << get_fileline() << ": warning: A for statement must "
"have a constant initial value to be synthesized "
<< get_process_type_as_string(pr_type) << endl;
}
// FIXME: Do the following also need to be supported in the condition?
// It would seem like they are hard to use to find the bounds.
// From NetEBinary
// What about NetEBits sig & constant, etc.
// From NetEUnary
// What about NetEUBits ! sig or ! (sig == constat)
// What about NetEUReduce &signal
if (const NetESignal*tmp = dynamic_cast<const NetESignal*>(condition_)) {
if (tmp->sig() != index_) {
print_for_idx_warning(this, "condition", pr_type, index_);
}
} else if (const NetEBComp*cmp = dynamic_cast<const NetEBComp*>(condition_)) {
check_for_bin_synth(cmp->left(), cmp->right(),
"compare against a constant", "condition",
this, pr_type, index_);
} else {
print_for_idx_warning(this, "condition", pr_type, index_);
}
if (const NetAssign*tmp = dynamic_cast<const NetAssign*>(step_statement_)) {
check_for_step_synth(tmp, this, pr_type, index_);
} else {
print_for_step_warning(this, pr_type);
}
if (statement_) result |= statement_->check_synth(pr_type, scope);
return result;
}
DelayType NetTaskDef::delay_type() const
// The delay check above has already marked this as an error.
bool NetPDelay::check_synth(ivl_process_type_t /* pr_type */,
const NetScope* /* scope */ ) const
{
return proc_->delay_type();
return false;
}
DelayType NetUTask::delay_type() const
bool NetRelease::check_synth(ivl_process_type_t pr_type,
const NetScope* /* scope */ ) const
{
return task()->task_def()->delay_type();
print_synth_warning(this, "A release", pr_type);
return false;
}
DelayType NetWhile::delay_type() const
bool NetRepeat::check_synth(ivl_process_type_t pr_type,
const NetScope* scope) const
{
ivl_assert(*this, proc_);
return get_loop_delay_type(cond_, proc_);
bool result = false;
print_synth_warning(this, "A repeat", pr_type);
if (statement_) result |= statement_->check_synth(pr_type, scope);
return result;
}
bool NetScope::check_synth(ivl_process_type_t pr_type,
const NetScope* /* scope */) const
{
bool result = false;
// Skip local events/signals
for (NetEvent*cur = events_ ; cur ; cur = cur->snext_) {
if (cur->local_flag()) continue;
cerr << cur->get_fileline() << ": warning: An event ("
<< cur->name() << ") cannot be synthesized "
<< get_process_type_as_string(pr_type) << endl;
}
for (signals_map_iter_t cur = signals_map_.begin();
cur != signals_map_.end() ; ++ cur) {
const NetNet*sig = cur->second;
if ((sig->data_type() != IVL_VT_BOOL) &&
(sig->data_type() != IVL_VT_LOGIC)) {
cerr << sig->get_fileline() << ": warning: A non-integral "
"variable (" << sig->name() << ") cannot be "
"synthesized "
<< get_process_type_as_string(pr_type) << endl;
}
}
return result;
}
bool NetSTask::check_synth(ivl_process_type_t pr_type,
const NetScope* /* scope */) const
{
if (strcmp(name(), "$ivl_darray_method$delete") == 0) {
cerr << get_fileline() << ": warning: Dynamic array "
"delete method cannot be synthesized "
<< get_process_type_as_string(pr_type) << endl;
} else {
cerr << get_fileline() << ": warning: System task ("
<< name() << ") cannot be synthesized "
<< get_process_type_as_string(pr_type) << endl;
}
return false;
}
bool NetTaskDef::check_synth(ivl_process_type_t pr_type,
const NetScope* /* scope */) const
{
bool result = false;
const NetScope *tscope = this->scope();
result |= tscope->check_synth(pr_type, tscope);
if (! tscope->is_auto()) {
cerr << tscope->get_def_file() << ":"
<< tscope->get_def_lineno()
<< ": warning: user task (" << tscope->basename()
<< ") must be automatic to be synthesized "
<< get_process_type_as_string(pr_type) << endl;
}
if (proc_) result |= proc_->check_synth(pr_type, tscope);
return result;
}
bool NetUTask::check_synth(ivl_process_type_t pr_type,
const NetScope* scope) const
{
return task()->task_def()->check_synth(pr_type, scope);
}
bool NetWhile::check_synth(ivl_process_type_t pr_type,
const NetScope* scope) const
{
bool result = false;
// A wait is already maked as an error in the delay check above.
if (! while_is_wait(cond_, proc_)) {
print_synth_warning(this, "A while", pr_type);
if (proc_) result |= proc_->check_synth(pr_type, scope);
}
return result;
}

216
netlist.h
View File

@ -1,7 +1,7 @@
#ifndef IVL_netlist_H
#define IVL_netlist_H
/*
* Copyright (c) 1998-2016 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-2017 Stephen Williams (steve@icarus.com)
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
@ -927,10 +927,13 @@ class NetScope : public Definitions, public Attrib {
public:
enum TYPE { MODULE, CLASS, TASK, FUNC, BEGIN_END, FORK_JOIN, GENBLOCK, PACKAGE };
/* Create a new scope, and attach it to the given parent. The
name is expected to have been permallocated. */
NetScope(NetScope*up, const hname_t&name, TYPE t, bool nest=false,
bool program=false, bool interface=false);
/* Create a new scope associated with a given compilation unit,
and attach it to the given parent. If no compilation unit is
specified, the parent's compilation unit is used. The name
is expected to have been permallocated. */
NetScope(NetScope*up, const hname_t&name, TYPE t, NetScope*in_unit=0,
bool nest=false, bool program=false, bool interface=false,
bool compilation_unit=false);
~NetScope();
/* Rename the scope using the name generated by inserting as
@ -1002,10 +1005,12 @@ class NetScope : public Definitions, public Attrib {
netclass_t* find_class(perm_string name);
/* The parent and child() methods allow users of NetScope
objects to locate nearby scopes. */
/* The unit(), parent(), and child() methods allow users of
NetScope objects to locate nearby scopes. */
NetScope* unit() { return unit_; }
NetScope* parent() { return up_; }
NetScope* child(const hname_t&name);
const NetScope* unit() const { return unit_; }
const NetScope* parent() const { return up_; }
const NetScope* child(const hname_t&name) const;
@ -1023,7 +1028,8 @@ class NetScope : public Definitions, public Attrib {
// Program blocks and interfaces have elaboration constraints.
inline bool program_block() const { return program_block_; }
inline bool is_interface() const { return is_interface_; }
TYPE type() const;
inline bool is_unit() const { return is_unit_; }
inline TYPE type() const { return type_; }
void print_type(ostream&) const;
// This provides a link to the variable initialisation process
@ -1152,6 +1158,9 @@ class NetScope : public Definitions, public Attrib {
perm_string local_symbol();
void dump(ostream&) const;
// Check to see if the scope has items that are not allowed
// in an always_comb/ff/latch process.
virtual bool check_synth(ivl_process_type_t pr_type, const NetScope*scope) const;
void emit_scope(struct target_t*tgt) const;
bool emit_defs(struct target_t*tgt) const;
@ -1249,6 +1258,8 @@ class NetScope : public Definitions, public Attrib {
bool program_block_;
// True if the scope is an interface
bool is_interface_;
// True if the scope is a compilation unit
bool is_unit_;
perm_string file_;
perm_string def_file_;
@ -1279,6 +1290,7 @@ class NetScope : public Definitions, public Attrib {
const PFunction*func_pform_;
unsigned elab_stage_;
NetScope*unit_;
NetScope*up_;
map<hname_t,NetScope*> children_;
@ -2036,7 +2048,7 @@ class NetExpr : public LineInfo {
// Get the Nexus that are the input to this
// expression. Normally this descends down to the reference to
// a signal that reads from its input.
virtual NexusSet* nex_input(bool rem_out = true) =0;
virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const =0;
// Return a version of myself that is structural. This is used
// for converting expressions to gates. The arguments are:
@ -2079,7 +2091,7 @@ class NetEArrayPattern : public NetExpr {
void dump(ostream&) const;
NetEArrayPattern* dup_expr() const;
NexusSet* nex_input(bool rem_out =true);
NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const;
private:
std::vector<NetExpr*> items_;
@ -2112,7 +2124,7 @@ class NetEConst : public NetExpr {
virtual NetEConst* dup_expr() const;
virtual NetNet*synthesize(Design*, NetScope*scope, NetExpr*);
virtual NexusSet* nex_input(bool rem_out = true);
virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const;
virtual NetExpr*evaluate_function(const LineInfo&loc,
map<perm_string,LocalVar>&ctx) const;
@ -2184,7 +2196,7 @@ class NetECReal : public NetExpr {
virtual NetECReal* dup_expr() const;
virtual NetNet*synthesize(Design*, NetScope*scope, NetExpr*);
virtual NexusSet* nex_input(bool rem_out = true);
virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const;
virtual NetExpr*evaluate_function(const LineInfo&loc,
map<perm_string,LocalVar>&ctx) const;
@ -2356,6 +2368,8 @@ class NetCaseCmp : public NetNode {
enum kind_t {
EEQ, // ===
NEQ, // !==
WEQ, // ==?
WNE, // !=?
XEQ, // casex guard tests
ZEQ // casez guard tests
};
@ -2626,7 +2640,7 @@ class NetProc : public virtual LineInfo {
// Find the nexa that are input by the statement. This is used
// for example by @* to find the inputs to the process for the
// sensitivity list.
virtual NexusSet* nex_input(bool rem_out = true);
virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const;
// Find the nexa that are set by the statement. Add the output
// values to the set passed as a parameter.
@ -2704,7 +2718,9 @@ class NetProc : public virtual LineInfo {
virtual void dump(ostream&, unsigned ind) const;
// Recursively checks to see if there is delay in this element.
virtual DelayType delay_type() const;
virtual DelayType delay_type(bool print_delay=false) const;
// Check to see if the item is synthesizable.
virtual bool check_synth(ivl_process_type_t pr_type, const NetScope*scope) const;
protected:
bool synth_async_block_substatement_(Design*des, NetScope*scope,
@ -2732,6 +2748,8 @@ class NetAlloc : public NetProc {
const NetScope* scope() const;
virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const;
virtual void nex_output(NexusSet&);
virtual bool emit_proc(struct target_t*) const;
virtual void dump(ostream&, unsigned ind) const;
@ -2839,7 +2857,7 @@ class NetAssign_ {
// being outputs. For example foo[idx] = ... is the l-value
// (NetAssign_ object) with a foo l-value and the input
// expression idx.
NexusSet* nex_input(bool rem_out = true);
NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const;
// Figuring out nex_output to process ultimately comes down to
// this method.
@ -2887,7 +2905,7 @@ class NetAssignBase : public NetProc {
void set_delay(NetExpr*);
const NetExpr* get_delay() const;
virtual NexusSet* nex_input(bool rem_out = true);
virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const;
virtual void nex_output(NexusSet&o);
@ -2902,6 +2920,7 @@ class NetAssignBase : public NetProc {
// This dumps all the lval structures.
void dump_lval(ostream&) const;
virtual void dump(ostream&, unsigned ind) const;
virtual bool check_synth(ivl_process_type_t pr_type, const NetScope*scope) const;
private:
NetAssign_*lval_;
@ -2923,6 +2942,7 @@ class NetAssign : public NetAssignBase {
virtual bool emit_proc(struct target_t*) const;
virtual int match_proc(struct proc_match_t*);
virtual void dump(ostream&, unsigned ind) const;
virtual bool check_synth(ivl_process_type_t pr_type, const NetScope*scope) const;
virtual bool evaluate_function(const LineInfo&loc,
map<perm_string,LocalVar>&ctx) const;
@ -2945,6 +2965,7 @@ class NetAssignNB : public NetAssignBase {
virtual bool emit_proc(struct target_t*) const;
virtual int match_proc(struct proc_match_t*);
virtual void dump(ostream&, unsigned ind) const;
virtual bool check_synth(ivl_process_type_t pr_type, const NetScope*scope) const;
unsigned nevents() const;
const NetEvent*event(unsigned) const;
@ -3002,12 +3023,13 @@ class NetBlock : public NetProc {
// for sequential blocks.
void emit_recurse(struct target_t*) const;
virtual NexusSet* nex_input(bool rem_out = true);
virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const;
virtual void nex_output(NexusSet&);
virtual bool emit_proc(struct target_t*) const;
virtual int match_proc(struct proc_match_t*);
virtual void dump(ostream&, unsigned ind) const;
virtual DelayType delay_type() const;
virtual DelayType delay_type(bool print_delay=false) const;
virtual bool check_synth(ivl_process_type_t pr_type, const NetScope*scope) const;
private:
const Type type_;
@ -3045,7 +3067,7 @@ class NetCase : public NetProc {
inline const NetExpr*expr(unsigned idx) const { return items_[idx].guard;}
inline const NetProc*stat(unsigned idx) const { return items_[idx].statement; }
virtual NexusSet* nex_input(bool rem_out = true);
virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const;
virtual void nex_output(NexusSet&out);
bool synth_async(Design*des, NetScope*scope,
@ -3054,7 +3076,8 @@ class NetCase : public NetProc {
virtual bool emit_proc(struct target_t*) const;
virtual void dump(ostream&, unsigned ind) const;
virtual DelayType delay_type() const;
virtual DelayType delay_type(bool print_delay=false) const;
virtual bool check_synth(ivl_process_type_t pr_type, const NetScope*scope) const;
virtual bool evaluate_function(const LineInfo&loc,
map<perm_string,LocalVar>&ctx) const;
@ -3091,9 +3114,9 @@ class NetCAssign : public NetAssignBase {
explicit NetCAssign(NetAssign_*lv, NetExpr*rv);
~NetCAssign();
virtual NexusSet* nex_input(bool rem_out = true);
virtual void dump(ostream&, unsigned ind) const;
virtual bool emit_proc(struct target_t*) const;
virtual bool check_synth(ivl_process_type_t pr_type, const NetScope*scope) const;
private: // not implemented
NetCAssign(const NetCAssign&);
@ -3124,7 +3147,7 @@ class NetCondit : public NetProc {
bool emit_recurse_if(struct target_t*) const;
bool emit_recurse_else(struct target_t*) const;
virtual NexusSet* nex_input(bool rem_out = true);
virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const;
virtual void nex_output(NexusSet&o);
bool is_asynchronous();
@ -3144,7 +3167,8 @@ class NetCondit : public NetProc {
virtual bool emit_proc(struct target_t*) const;
virtual int match_proc(struct proc_match_t*);
virtual void dump(ostream&, unsigned ind) const;
virtual DelayType delay_type() const;
virtual DelayType delay_type(bool print_delay=false) const;
virtual bool check_synth(ivl_process_type_t pr_type, const NetScope*scope) const;
virtual bool evaluate_function(const LineInfo&loc,
map<perm_string,LocalVar>&ctx) const;
@ -3190,6 +3214,7 @@ class NetDeassign : public NetAssignBase {
virtual bool emit_proc(struct target_t*) const;
virtual void dump(ostream&, unsigned ind) const;
virtual bool check_synth(ivl_process_type_t pr_type, const NetScope*scope) const;
private: // not implemented
NetDeassign(const NetDeassign&);
@ -3213,8 +3238,11 @@ class NetDisable : public NetProc {
const NetScope*target() const;
virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const;
virtual void nex_output(NexusSet&);
virtual bool emit_proc(struct target_t*) const;
virtual void dump(ostream&, unsigned ind) const;
virtual bool check_synth(ivl_process_type_t pr_type, const NetScope*scope) const;
virtual bool evaluate_function(const LineInfo&loc,
map<perm_string,LocalVar>&ctx) const;
@ -3241,11 +3269,12 @@ class NetDoWhile : public NetProc {
void emit_proc_recurse(struct target_t*) const;
virtual NexusSet* nex_input(bool rem_out = true);
virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const;
virtual void nex_output(NexusSet&);
virtual bool emit_proc(struct target_t*) const;
virtual void dump(ostream&, unsigned ind) const;
virtual DelayType delay_type() const;
virtual DelayType delay_type(bool print_delay=false) const;
virtual bool check_synth(ivl_process_type_t pr_type, const NetScope*scope) const;
virtual bool evaluate_function(const LineInfo&loc,
map<perm_string,LocalVar>&ctx) const;
@ -3302,6 +3331,9 @@ class NetEvent : public LineInfo {
perm_string name() const;
bool local_flag() const { return local_flag_; }
void local_flag(bool f) { local_flag_ = f; }
// Get information about probes connected to me.
unsigned nprobe() const;
NetEvProbe* probe(unsigned);
@ -3333,6 +3365,7 @@ class NetEvent : public LineInfo {
private:
perm_string name_;
bool local_flag_;
// The NetScope class uses these to list the events.
NetScope*scope_;
@ -3370,8 +3403,11 @@ class NetEvTrig : public NetProc {
const NetEvent*event() const;
virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const;
virtual void nex_output(NexusSet&);
virtual bool emit_proc(struct target_t*) const;
virtual void dump(ostream&, unsigned ind) const;
virtual bool check_synth(ivl_process_type_t pr_type, const NetScope*scope) const;
private:
NetEvent*event_;
@ -3387,12 +3423,15 @@ class NetEvWait : public NetProc {
void add_event(NetEvent*tgt);
void replace_event(NetEvent*orig, NetEvent*repl);
inline void set_t0_trigger() { has_t0_trigger_ = true; };
inline unsigned nevents() const { return events_.size(); }
inline const NetEvent*event(unsigned idx) const { return events_[idx]; }
inline NetEvent*event(unsigned idx) { return events_[idx]; }
inline bool has_t0_trigger() const { return has_t0_trigger_; };
NetProc*statement();
const NetProc*statement() const;
virtual bool emit_proc(struct target_t*) const;
bool emit_recurse(struct target_t*) const;
@ -3406,7 +3445,7 @@ class NetEvWait : public NetProc {
// process? This method checks.
virtual bool is_synchronous();
virtual NexusSet* nex_input(bool rem_out = true);
virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const;
virtual void nex_output(NexusSet&out);
virtual bool synth_async(Design*des, NetScope*scope,
@ -3425,12 +3464,14 @@ class NetEvWait : public NetProc {
virtual void dump(ostream&, unsigned ind) const;
// This will ignore any statement.
virtual void dump_inline(ostream&) const;
virtual DelayType delay_type() const;
virtual DelayType delay_type(bool print_delay=false) const;
virtual bool check_synth(ivl_process_type_t pr_type, const NetScope*scope) const;
private:
NetProc*statement_;
// Events that I might wait for.
std::vector<NetEvent*>events_;
bool has_t0_trigger_;
};
ostream& operator << (ostream&out, const NetEvWait&obj);
@ -3473,10 +3514,9 @@ class NetForce : public NetAssignBase {
explicit NetForce(NetAssign_*l, NetExpr*r);
~NetForce();
virtual NexusSet* nex_input(bool rem_out = true);
virtual void dump(ostream&, unsigned ind) const;
virtual bool emit_proc(struct target_t*) const;
virtual bool check_synth(ivl_process_type_t pr_type, const NetScope*scope) const;
};
/*
@ -3491,10 +3531,12 @@ class NetForever : public NetProc {
void emit_recurse(struct target_t*) const;
virtual NexusSet* nex_input(bool rem_out = true);
virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const;
virtual void nex_output(NexusSet&);
virtual bool emit_proc(struct target_t*) const;
virtual void dump(ostream&, unsigned ind) const;
virtual DelayType delay_type() const;
virtual DelayType delay_type(bool print_delay=false) const;
virtual bool check_synth(ivl_process_type_t pr_type, const NetScope*scope) const;
virtual bool evaluate_function(const LineInfo&loc,
map<perm_string,LocalVar>&ctx) const;
@ -3513,11 +3555,12 @@ class NetForLoop : public NetProc {
void emit_recurse(struct target_t*) const;
virtual NexusSet* nex_input(bool rem_out = true);
virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const;
virtual void nex_output(NexusSet&);
virtual bool emit_proc(struct target_t*) const;
virtual void dump(ostream&, unsigned ind) const;
virtual DelayType delay_type() const;
virtual DelayType delay_type(bool print_delay=false) const;
virtual bool check_synth(ivl_process_type_t pr_type, const NetScope*scope) const;
virtual bool evaluate_function(const LineInfo&loc,
map<perm_string,LocalVar>&ctx) const;
@ -3550,6 +3593,8 @@ class NetFree : public NetProc {
const NetScope* scope() const;
virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const;
virtual void nex_output(NexusSet&);
virtual bool emit_proc(struct target_t*) const;
virtual void dump(ostream&, unsigned ind) const;
@ -3613,12 +3658,13 @@ class NetPDelay : public NetProc {
uint64_t delay() const;
const NetExpr*expr() const;
virtual NexusSet* nex_input(bool rem_out = true);
virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const;
virtual void nex_output(NexusSet&);
virtual bool emit_proc(struct target_t*) const;
virtual void dump(ostream&, unsigned ind) const;
virtual DelayType delay_type() const;
virtual DelayType delay_type(bool print_delay=false) const;
virtual bool check_synth(ivl_process_type_t pr_type, const NetScope*scope) const;
bool emit_proc_recurse(struct target_t*) const;
@ -3640,10 +3686,12 @@ class NetRepeat : public NetProc {
const NetExpr*expr() const;
void emit_recurse(struct target_t*) const;
virtual NexusSet* nex_input(bool rem_out = true);
virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const;
virtual void nex_output(NexusSet&);
virtual bool emit_proc(struct target_t*) const;
virtual void dump(ostream&, unsigned ind) const;
virtual DelayType delay_type() const;
virtual DelayType delay_type(bool print_delay=false) const;
virtual bool check_synth(ivl_process_type_t pr_type, const NetScope*scope) const;
virtual bool evaluate_function(const LineInfo&loc,
map<perm_string,LocalVar>&ctx) const;
@ -3666,6 +3714,7 @@ class NetRelease : public NetAssignBase {
virtual bool emit_proc(struct target_t*) const;
virtual void dump(ostream&, unsigned ind) const;
virtual bool check_synth(ivl_process_type_t pr_type, const NetScope*scope) const;
private:
};
@ -3691,10 +3740,11 @@ class NetSTask : public NetProc {
const NetExpr* parm(unsigned idx) const;
virtual NexusSet* nex_input(bool rem_out = true);
virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const;
virtual void nex_output(NexusSet&);
virtual bool emit_proc(struct target_t*) const;
virtual void dump(ostream&, unsigned ind) const;
virtual bool check_synth(ivl_process_type_t pr_type, const NetScope*scope) const;
virtual bool evaluate_function(const LineInfo&loc,
map<perm_string,LocalVar>&ctx) const;
@ -3724,7 +3774,8 @@ class NetTaskDef : public NetBaseDef {
~NetTaskDef();
void dump(ostream&, unsigned) const;
DelayType delay_type() const;
DelayType delay_type(bool print_delay=false) const;
virtual bool check_synth(ivl_process_type_t pr_type, const NetScope*scope) const;
private: // not implemented
NetTaskDef(const NetTaskDef&);
@ -3750,7 +3801,7 @@ class NetELast : public NetExpr {
virtual void expr_scan(struct expr_scan_t*) const;
virtual NetELast*dup_expr() const;
virtual NexusSet* nex_input(bool rem_out = true);
virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const;
private:
NetNet*sig_;
@ -3779,7 +3830,7 @@ class NetEUFunc : public NetExpr {
virtual void expr_scan(struct expr_scan_t*) const;
virtual NetEUFunc*dup_expr() const;
virtual NexusSet* nex_input(bool rem_out = true);
virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const;
virtual NetExpr* eval_tree();
virtual NetExpr*evaluate_function(const LineInfo&loc,
map<perm_string,LocalVar>&ctx) const;
@ -3815,7 +3866,7 @@ class NetEAccess : public NetExpr {
virtual void expr_scan(struct expr_scan_t*) const;
virtual NetEAccess*dup_expr() const;
virtual NexusSet* nex_input(bool rem_out = true);
virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const;
private:
NetBranch*branch_;
@ -3837,11 +3888,12 @@ class NetUTask : public NetProc {
const NetScope* task() const;
virtual NexusSet* nex_input(bool rem_out = true);
virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const;
virtual void nex_output(NexusSet&);
virtual bool emit_proc(struct target_t*) const;
virtual void dump(ostream&, unsigned ind) const;
virtual DelayType delay_type() const;
virtual DelayType delay_type(bool print_delay=false) const;
virtual bool check_synth(ivl_process_type_t pr_type, const NetScope*scope) const;
private:
NetScope*task_;
@ -3862,16 +3914,17 @@ class NetWhile : public NetProc {
void emit_proc_recurse(struct target_t*) const;
virtual NexusSet* nex_input(bool rem_out = true);
virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const;
virtual void nex_output(NexusSet&);
virtual bool emit_proc(struct target_t*) const;
virtual void dump(ostream&, unsigned ind) const;
virtual DelayType delay_type() const;
virtual DelayType delay_type(bool print_delay=false) const;
virtual bool check_synth(ivl_process_type_t pr_type, const NetScope*scope) const;
virtual bool evaluate_function(const LineInfo&loc,
map<perm_string,LocalVar>&ctx) const;
private:
NetExpr* cond_;
NetExpr*cond_;
NetProc*proc_;
};
@ -4005,7 +4058,7 @@ class NetEBinary : public NetExpr {
virtual NetExpr* eval_tree();
virtual NetExpr* evaluate_function(const LineInfo&loc,
map<perm_string,LocalVar>&ctx) const;
virtual NexusSet* nex_input(bool rem_out = true);
virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const;
virtual void expr_scan(struct expr_scan_t*) const;
virtual void dump(ostream&) const;
@ -4128,6 +4181,7 @@ class NetEBComp : public NetEBinary {
NetEConst*eval_gt_(const NetExpr*le, const NetExpr*re) const;
NetEConst*eval_gteq_(const NetExpr*le, const NetExpr*re) const;
NetEConst*eval_eqeqeq_(bool ne_flag, const NetExpr*le, const NetExpr*re) const;
NetEConst*eval_weqeq_(bool ne_flag, const NetExpr*le, const NetExpr*re) const;
};
/*
@ -4258,7 +4312,7 @@ class NetEConcat : public NetExpr {
NetExpr* parm(unsigned idx) const { return parms_[idx]; }
virtual ivl_variable_type_t expr_type() const;
virtual NexusSet* nex_input(bool rem_out = true);
virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const;
virtual bool has_width() const;
virtual NetEConcat* dup_expr() const;
virtual NetEConst* eval_tree();
@ -4306,7 +4360,7 @@ class NetESelect : public NetExpr {
// sub-expression.
virtual ivl_variable_type_t expr_type() const;
virtual NexusSet* nex_input(bool rem_out = true);
virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const;
virtual bool has_width() const;
virtual void expr_scan(struct expr_scan_t*) const;
virtual NetEConst* eval_tree();
@ -4335,7 +4389,7 @@ class NetEEvent : public NetExpr {
virtual void expr_scan(struct expr_scan_t*) const;
virtual NetEEvent* dup_expr() const;
virtual NexusSet* nex_input(bool rem_out = true);
virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const;
virtual void dump(ostream&os) const;
@ -4358,7 +4412,7 @@ class NetENetenum : public NetExpr {
virtual void expr_scan(struct expr_scan_t*) const;
virtual NetENetenum* dup_expr() const;
virtual NexusSet* nex_input(bool rem_out = true);
virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const;
virtual void dump(ostream&os) const;
@ -4382,7 +4436,7 @@ class NetENew : public NetExpr {
virtual void expr_scan(struct expr_scan_t*) const;
virtual NetENew* dup_expr() const;
virtual NexusSet* nex_input(bool rem_out = true);
virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const;
virtual void dump(ostream&os) const;
@ -4404,7 +4458,7 @@ class NetENull : public NetExpr {
virtual void expr_scan(struct expr_scan_t*) const;
virtual NetENull* dup_expr() const;
virtual NexusSet* nex_input(bool rem_out = true);
virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const;
virtual void dump(ostream&os) const;
};
@ -4430,7 +4484,7 @@ class NetEProperty : public NetExpr {
ivl_variable_type_t expr_type() const;
virtual void expr_scan(struct expr_scan_t*) const;
virtual NetEProperty* dup_expr() const;
virtual NexusSet* nex_input(bool rem_out = true);
virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const;
virtual void dump(ostream&os) const;
@ -4455,7 +4509,7 @@ class NetEScope : public NetExpr {
virtual void expr_scan(struct expr_scan_t*) const;
virtual NetEScope* dup_expr() const;
virtual NexusSet* nex_input(bool rem_out = true);
virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const;
virtual void dump(ostream&os) const;
@ -4489,7 +4543,7 @@ class NetESFunc : public NetExpr {
map<perm_string,LocalVar>&ctx) const;
virtual ivl_variable_type_t expr_type() const;
virtual NexusSet* nex_input(bool rem_out = true);
virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const;
virtual const netenum_t* enumeration() const;
virtual void dump(ostream&) const;
@ -4551,7 +4605,7 @@ class NetESFunc : public NetExpr {
/* Added in SystemVerilog 2009 and later. */
CTONES = 0x00020024, /* $countones takes one argument. */
/* Added in SystemVerilog 2012 and later. */
CTBITS = 0xfffe0025, /* $countbits takes one or more arguments. */
CTBITS = 0xfffc0025, /* $countbits takes two or more arguments. */
/* Added as Icarus extensions to Verilog-A. */
ABS = 0x00020026, /* $abs takes one argument. */
MAX = 0x00040027, /* $max takes two argument. */
@ -4561,7 +4615,7 @@ class NetESFunc : public NetExpr {
bool takes_nargs_(ID func, unsigned nargs) {
if (nargs > 15) nargs = 15;
return func & (1 << (nargs + 16));
return func & (1U << (nargs + 16));
}
const char* name_;
@ -4603,8 +4657,7 @@ class NetESFunc : public NetExpr {
NetEConst* evaluate_array_funcs_(ID id,
const NetExpr*arg0,
const NetExpr*arg1) const;
NetEConst* evaluate_countbits_(const NetExpr*arg0,
const NetExpr*arg1) const;
NetEConst* evaluate_countbits_(void) const;
public:
bool is_built_in() const { return built_in_id_() != NOT_BUILT_IN; };
@ -4624,7 +4677,7 @@ class NetEShallowCopy : public NetExpr {
virtual void expr_scan(struct expr_scan_t*) const;
virtual NetEShallowCopy* dup_expr() const;
virtual NexusSet* nex_input(bool rem_out = true);
virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const;
virtual void dump(ostream&os) const;
@ -4656,7 +4709,7 @@ class NetETernary : public NetExpr {
virtual NetExpr*evaluate_function(const LineInfo&loc,
map<perm_string,LocalVar>&ctx) const;
virtual ivl_variable_type_t expr_type() const;
virtual NexusSet* nex_input(bool rem_out = true);
virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const;
virtual void expr_scan(struct expr_scan_t*) const;
virtual void dump(ostream&) const;
virtual NetNet*synthesize(Design*, NetScope*scope, NetExpr*root);
@ -4711,7 +4764,7 @@ class NetEUnary : public NetExpr {
virtual NetNet* synthesize(Design*, NetScope*scope, NetExpr*root);
virtual ivl_variable_type_t expr_type() const;
virtual NexusSet* nex_input(bool rem_out = true);
virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const;
virtual void expr_scan(struct expr_scan_t*) const;
virtual void dump(ostream&) const;
@ -4787,7 +4840,7 @@ class NetESignal : public NetExpr {
virtual NetESignal* dup_expr() const;
NetNet* synthesize(Design*des, NetScope*scope, NetExpr*root);
NexusSet* nex_input(bool rem_out = true);
NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const;
const netenum_t*enumeration() const;
virtual NetExpr*evaluate_function(const LineInfo&loc,
@ -4835,7 +4888,7 @@ struct elaborator_work_item_t {
* This class contains an entire design. It includes processes and a
* netlist, and can be passed around from function to function.
*/
class Design : public Definitions {
class Design {
public:
Design();
@ -4857,12 +4910,13 @@ class Design : public Definitions {
const char* get_flag(const string&key) const;
NetScope* make_root_scope(perm_string name, bool program_block,
bool is_interface);
NetScope* make_root_scope(perm_string name, NetScope*unit_scope,
bool program_block, bool is_interface);
NetScope* find_root_scope();
std::list<NetScope*> find_root_scopes() const;
NetScope* make_package_scope(perm_string name);
NetScope* make_package_scope(perm_string name, NetScope*unit_scope,
bool is_unit);
std::list<NetScope*> find_package_scopes() const;
/* Attempt to set the precision to the specified value. If the
@ -4912,11 +4966,6 @@ class Design : public Definitions {
// Look for defparams that never matched, and print warnings.
void residual_defparams();
// Do elaborate_sig for objects in $root scope.
void root_elaborate_sig(void);
void root_elaborate(void);
/* This method locates a signal, starting at a given
scope. The name parameter may be partially hierarchical, so
this method, unlike the NetScope::find_signal method,
@ -4929,12 +4978,6 @@ class Design : public Definitions {
// Tasks
NetScope* find_task(NetScope*scope, const pform_name_t&name);
void add_root_task(NetScope*tscope, PTaskFunc*tf);
std::list<NetScope*> find_roottask_scopes(void) const;
// Find a class in the $root scope.
void add_class(netclass_t*cl, PClass*pclass);
netclass_t* find_class(perm_string name) const;
// NODES
void add_node(NetNode*);
@ -4948,6 +4991,7 @@ class Design : public Definitions {
void add_process(NetAnalogTop*);
void delete_process(NetProcTop*);
bool check_proc_delay() const;
bool check_proc_synth() const;
NetNet* find_discipline_reference(ivl_discipline_t dis, NetScope*scope);
@ -4962,6 +5006,12 @@ class Design : public Definitions {
unsigned errors;
private:
NetScope* find_scope_(NetScope*, const hname_t&name,
NetScope::TYPE type = NetScope::MODULE) const;
NetScope* find_scope_(NetScope*, const std::list<hname_t>&path,
NetScope::TYPE type = NetScope::MODULE) const;
// Keep a tree of scopes. The NetScope class handles the wide
// tree and per-hop searches for me.
list<NetScope*>root_scopes_;
@ -4970,12 +5020,6 @@ class Design : public Definitions {
// packages do not nest.
std::map<perm_string,NetScope*>packages_;
// Tasks in the $root scope
std::map<NetScope*,PTaskFunc*>root_tasks_;
// Need this for elaboration of $root scope pclass objects.
std::map<netclass_t*,PClass*> class_to_pclass_;
// List the nodes in the design.
NetNode*nodes_;
// These are in support of the node functor iterator.

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2016 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-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
@ -1260,6 +1260,8 @@ const char *human_readable_op(const char op, bool unary)
if (unary) type = "~|"; // NOR
else type = "!=="; // Case inequality
break;
case 'w': type = "==?"; break; // Wild equality
case 'W': type = "!=?"; break; // Wild inequality
case 'l': type = "<<(<)"; break; // Left shifts
case 'r': type = ">>"; break; // Logical right shift
@ -1665,3 +1667,38 @@ NetScope* find_method_containing_scope(const LineInfo&, NetScope*scope)
return scope;
}
/*
* Print a warning if we find a mixture of default and explicit timescale
* based delays in the design, since this is likely an error.
*/
void check_for_inconsistent_delays(NetScope*scope)
{
static bool used_implicit_timescale = false;
static bool used_explicit_timescale = false;
static bool display_ts_dly_warning = true;
if (scope->time_from_timescale())
used_explicit_timescale = true;
else
used_implicit_timescale = true;
if (display_ts_dly_warning &&
used_explicit_timescale &&
used_implicit_timescale) {
if (gn_system_verilog()) {
cerr << "warning: Found both default and explicit "
"timescale based delays. Use" << endl;
cerr << " : -Wtimescale to find the design "
"element(s) with no explicit" << endl;
cerr << " : timescale." << endl;
} else {
cerr << "warning: Found both default and "
"`timescale based delays. Use" << endl;
cerr << " : -Wtimescale to find the "
"module(s) with no `timescale." << endl;
}
display_ts_dly_warning = false;
}
}

View File

@ -1,7 +1,7 @@
#ifndef IVL_netmisc_H
#define IVL_netmisc_H
/*
* Copyright (c) 1999-2016 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-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
@ -378,10 +378,6 @@ const char *human_readable_op(const char op, bool unary = false);
enum const_bool { C_NON, C_0, C_1, C_X };
const_bool const_logical(const NetExpr*expr);
extern bool dly_used_no_timescale;
extern bool dly_used_timescale;
extern bool display_ts_dly_warning;
/*
* When scaling a real value to a time we need to do some standard
* processing.
@ -409,4 +405,10 @@ extern void assign_unpacked_with_bufz(Design*des, NetScope*scope,
extern NetPartSelect* detect_partselect_lval(Link&pin);
/*
* Print a warning if we find a mixture of default and explicit timescale
* based delays in the design, since this is likely an error.
*/
extern void check_for_inconsistent_delays(NetScope*scope);
#endif /* IVL_netmisc_H */

257
parse.y
View File

@ -1,7 +1,7 @@
%{
/*
* Copyright (c) 1998-2016 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-2017 Stephen Williams (steve@icarus.com)
* Copyright CERN 2012-2013 / Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
@ -35,9 +35,6 @@ class PSpecPath;
extern void lex_end_table();
bool have_timeunit_decl = false;
bool have_timeprec_decl = false;
static list<pform_range_t>* param_active_range = 0;
static bool param_active_signed = false;
static ivl_variable_type_t param_active_type = IVL_VT_LOGIC;
@ -468,7 +465,7 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
%token <number> BASED_NUMBER DEC_NUMBER UNBASED_NUMBER
%token <realtime> REALTIME
%token K_PLUS_EQ K_MINUS_EQ K_INCR K_DECR
%token K_LE K_GE K_EG K_EQ K_NE K_CEQ K_CNE K_LP K_LS K_RS K_RSS K_SG
%token K_LE K_GE K_EG K_EQ K_NE K_CEQ K_CNE K_WEQ K_WNE K_LP K_LS K_RS K_RSS K_SG
/* K_CONTRIBUTE is <+, the contribution assign. */
%token K_CONTRIBUTE
%token K_PO_POS K_PO_NEG K_POW
@ -532,8 +529,6 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
%token K_tagged K_this K_throughout K_timeprecision K_timeunit K_type
%token K_typedef K_union K_unique K_var K_virtual K_void K_wait_order
%token K_wildcard K_with K_within
/* Fake tokens that are passed once we have an initial token. */
%token K_timeprecision_check K_timeunit_check
/* The new tokens from 1800-2009. */
%token K_accept_on K_checker K_endchecker K_eventually K_global K_implies
@ -598,7 +593,7 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
%type <tf_ports> function_item function_item_list function_item_list_opt
%type <tf_ports> task_item task_item_list task_item_list_opt
%type <tf_ports> tf_port_declaration tf_port_item tf_port_list tf_port_list_opt
%type <tf_ports> tf_port_declaration tf_port_item tf_port_item_list tf_port_list tf_port_list_opt
%type <named_pexpr> modport_simple_port port_name parameter_value_byname
%type <named_pexprs> port_name_list parameter_value_byname_list
@ -627,6 +622,7 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
%type <decl_assignments> list_of_variable_decl_assignments
%type <data_type> data_type data_type_or_implicit data_type_or_implicit_or_void
%type <data_type> simple_type_or_string
%type <class_type> class_identifier
%type <struct_member> struct_union_member
%type <struct_members> struct_union_member_list
@ -655,6 +651,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
@ -682,7 +679,7 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
%left '|'
%left '^' K_NXOR K_NOR
%left '&' K_NAND
%left K_EQ K_NE K_CEQ K_CNE
%left K_EQ K_NE K_CEQ K_CNE K_WEQ K_WNE
%left K_GE K_LE '<' '>'
%left K_LS K_RS K_RSS
%left '+' '-'
@ -691,7 +688,7 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
%left UNARY_PREC
/* to resolve dangling else ambiguity. */
/* to resolve dangling else ambiguity. */
%nonassoc less_than_K_else
%nonassoc K_else
@ -699,12 +696,22 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
%nonassoc '('
%nonassoc K_exclude
/* to resolve timeunits declaration/redeclaration ambiguity */
%nonassoc no_timeunits_declaration
%nonassoc one_timeunits_declaration
%nonassoc K_timeunit K_timeprecision
%%
/* IEEE1800-2005: A.1.2 */
/* source_text ::= [ timeunits_declaration ] { description } */
source_text : description_list | ;
source_text
: timeunits_declaration_opt
{ pform_set_scope_timescale(yyloc); }
description_list
| /* empty */
;
assertion_item /* IEEE1800-2012: A.6.10 */
: concurrent_assertion_item
@ -1136,11 +1143,7 @@ data_type_or_implicit_or_void
}
;
/* NOTE 1: We pull the "timeunits_declaration" into the description
here in order to be a little more flexible with where timeunits
statements may go. This may be a bad idea, but it is legacy now. */
/* NOTE 2: The "module" rule of the description combines the
/* NOTE: The "module" rule of the description combines the
module_declaration, program_declaration, and interface_declaration
rules from the standard description. */
@ -1725,17 +1728,18 @@ open_range_list /* IEEE1800-2005 A.2.11 */
package_declaration /* IEEE1800-2005 A.1.2 */
: K_package lifetime_opt IDENTIFIER ';'
{ pform_start_package_declaration(@1, $3, $2);
}
{ pform_start_package_declaration(@1, $3, $2); }
timeunits_declaration_opt
{ pform_set_scope_timescale(@1); }
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 ($8) {
if (strcmp($3,$8) != 0) {
yyerror(@8, "error: End label doesn't match package name");
if ($10) {
if (strcmp($3,$10) != 0) {
yyerror(@10, "error: End label doesn't match package name");
}
delete[]$8;
delete[]$10;
}
delete[]$3;
}
@ -1815,6 +1819,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. */
@ -1865,6 +1884,60 @@ signing /* IEEE1800-2005: A.2.2.1 */
| K_unsigned { $$ = false; }
;
simple_type_or_string /* IEEE1800-2005: A.2.2.1 */
: integer_vector_type
{ ivl_variable_type_t use_vtype = $1;
bool reg_flag = false;
if (use_vtype == IVL_VT_NO_TYPE) {
use_vtype = IVL_VT_LOGIC;
reg_flag = true;
}
vector_type_t*tmp = new vector_type_t(use_vtype, false, 0);
tmp->reg_flag = reg_flag;
FILE_NAME(tmp, @1);
$$ = tmp;
}
| non_integer_type
{ real_type_t*tmp = new real_type_t($1);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| atom2_type
{ atom2_type_t*tmp = new atom2_type_t($1, true);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| K_integer
{ list<pform_range_t>*pd = make_range_from_width(integer_width);
vector_type_t*tmp = new vector_type_t(IVL_VT_LOGIC, true, pd);
tmp->reg_flag = true;
tmp->integer_flag = true;
$$ = tmp;
}
| K_time
{ list<pform_range_t>*pd = make_range_from_width(64);
vector_type_t*tmp = new vector_type_t(IVL_VT_LOGIC, false, pd);
tmp->reg_flag = !gn_system_verilog();
$$ = tmp;
}
| TYPE_IDENTIFIER
{ $$ = $1.type;
delete[]$1.text;
}
| PACKAGE_IDENTIFIER K_SCOPE_RES
{ lex_in_package_scope($1); }
TYPE_IDENTIFIER
{ lex_in_package_scope(0);
$$ = $4.type;
delete[]$4.text;
}
| K_string
{ string_type_t*tmp = new string_type_t;
FILE_NAME(tmp, @1);
$$ = tmp;
}
;
statement /* IEEE1800-2005: A.6.4 */
: attribute_list_opt statement_item
{ pform_bind_attributes($2->attributes, $1);
@ -2028,7 +2101,10 @@ task_declaration /* IEEE1800-2005: A.2.7 */
| K_task lifetime_opt IDENTIFIER error K_endtask
{
assert(current_task == 0);
if (current_task) {
pform_pop_scope();
current_task = 0;
}
}
endlabel_opt
{ // Last step: check any closing name. This is done late so
@ -2112,10 +2188,16 @@ tf_port_item /* IEEE1800-2005: A.2.7 */
: port_direction_opt data_type_or_implicit IDENTIFIER dimensions_opt tf_port_item_expr_opt
{ vector<pform_tf_port_t>*tmp;
NetNet::PortType use_port_type = $1==NetNet::PIMPLICIT? NetNet::PINPUT : $1;
NetNet::PortType use_port_type = $1;
if ((use_port_type == NetNet::PIMPLICIT) && (gn_system_verilog() || ($2 == 0)))
use_port_type = port_declaration_context.port_type;
perm_string name = lex_strings.make($3);
list<perm_string>* ilist = list_from_identifier($3);
if (use_port_type == NetNet::PIMPLICIT) {
yyerror(@1, "error: missing task/function port direction.");
use_port_type = NetNet::PINPUT; // for error recovery
}
if (($2 == 0) && ($1==NetNet::PIMPLICIT)) {
// Detect special case this is an undecorated
// identifier and we need to get the declaration from
@ -2127,7 +2209,6 @@ tf_port_item /* IEEE1800-2005: A.2.7 */
port_declaration_context.data_type,
ilist);
} else {
// Otherwise, the decorations for this identifier
// indicate the type. Save the type for any right
@ -2174,8 +2255,15 @@ tf_port_item_expr_opt
;
tf_port_list /* IEEE1800-2005: A.2.7 */
: { port_declaration_context.port_type = gn_system_verilog() ? NetNet::PINPUT : NetNet::PIMPLICIT;
port_declaration_context.data_type = 0;
}
tf_port_item_list
{ $$ = $2; }
;
: tf_port_list ',' tf_port_item
tf_port_item_list
: tf_port_item_list ',' tf_port_item
{ vector<pform_tf_port_t>*tmp;
if ($1 && $3) {
size_t s1 = $1->size();
@ -2201,30 +2289,34 @@ tf_port_list /* IEEE1800-2005: A.2.7 */
{ yyerror(@2, "error: Syntax error in task/function port declaration.");
$$ = $3;
}
| tf_port_list ','
| tf_port_item_list ','
{ yyerror(@2, "error: NULL port declarations are not allowed.");
$$ = $1;
}
| tf_port_list ';'
| tf_port_item_list ';'
{ yyerror(@2, "error: ';' is an invalid port declaration separator.");
$$ = $1;
}
;
/* NOTE: Icarus Verilog is a little more generous with the
timeunits declarations by allowing them to happen in multiple
places in the file. So the rule is adjusted to be invoked by the
"description" rule. This theoretically allows files to be
concatenated together and still compile. */
timeunits_declaration /* IEEE1800-2005: A.1.2 */
: K_timeunit TIME_LITERAL ';'
{ pform_set_timeunit($2, false, false); }
{ pform_set_timeunit($2, allow_timeunit_decl); }
| K_timeunit TIME_LITERAL '/' TIME_LITERAL ';'
{ pform_set_timeunit($2, false, false);
pform_set_timeprecision($4, false, false);
{ bool initial_decl = allow_timeunit_decl && allow_timeprec_decl;
pform_set_timeunit($2, initial_decl);
pform_set_timeprec($4, initial_decl);
}
| K_timeprecision TIME_LITERAL ';'
{ pform_set_timeprecision($2, false, false); }
{ pform_set_timeprec($2, allow_timeprec_decl); }
;
/* Allow zero, one, or two declarations. The second declaration might
be a repeat declaration, but the pform functions take care of that. */
timeunits_declaration_opt
: /* empty */ %prec no_timeunits_declaration
| timeunits_declaration %prec one_timeunits_declaration
| timeunits_declaration timeunits_declaration
;
value_range /* IEEE1800-2005: A.8.3 */
@ -3259,6 +3351,11 @@ expression
FILE_NAME(tmp, @2);
$$ = tmp;
}
| expression K_WEQ attribute_list_opt expression
{ PEBinary*tmp = new PEBComp('w', $1, $4);
FILE_NAME(tmp, @2);
$$ = tmp;
}
| expression K_LE attribute_list_opt expression
{ PEBinary*tmp = new PEBComp('L', $1, $4);
FILE_NAME(tmp, @2);
@ -3279,6 +3376,11 @@ expression
FILE_NAME(tmp, @2);
$$ = tmp;
}
| expression K_WNE attribute_list_opt expression
{ PEBinary*tmp = new PEBComp('W', $1, $4);
FILE_NAME(tmp, @2);
$$ = tmp;
}
| expression K_LOR attribute_list_opt expression
{ PEBinary*tmp = new PEBLogic('o', $1, $4);
FILE_NAME(tmp, @2);
@ -3751,7 +3853,7 @@ expr_primary
}
}
| data_type '\'' '(' expression ')'
| simple_type_or_string '\'' '(' expression ')'
{ PExpr*base = $4;
if (gn_system_verilog()) {
PECastType*tmp = new PECastType($1, base);
@ -4390,47 +4492,6 @@ cont_assign_list
{ $$ = $1; }
;
/* We allow zero, one or two unique declarations. */
local_timeunit_prec_decl_opt
: /* Empty */
| K_timeunit TIME_LITERAL '/' TIME_LITERAL ';'
{ pform_set_timeunit($2, true, false);
have_timeunit_decl = true;
pform_set_timeprecision($4, true, false);
have_timeprec_decl = true;
}
| local_timeunit_prec_decl
| local_timeunit_prec_decl local_timeunit_prec_decl2
;
/* By setting the appropriate have_time???_decl we allow only
one declaration of each type in this module. */
local_timeunit_prec_decl
: K_timeunit TIME_LITERAL ';'
{ pform_set_timeunit($2, true, false);
have_timeunit_decl = true;
}
| K_timeprecision TIME_LITERAL ';'
{ pform_set_timeprecision($2, true, false);
have_timeprec_decl = true;
}
;
local_timeunit_prec_decl2
: K_timeunit TIME_LITERAL ';'
{ pform_set_timeunit($2, true, false);
have_timeunit_decl = true;
}
| K_timeprecision TIME_LITERAL ';'
{ pform_set_timeprecision($2, true, false);
have_timeprec_decl = true;
}
/* As the second item this form is always a check. */
| K_timeunit TIME_LITERAL '/' TIME_LITERAL ';'
{ pform_set_timeunit($2, true, true);
pform_set_timeprecision($4, true, true);
}
;
/* This is the global structure of a module. A module is a start
section, with optional ports, then an optional list of module
items, and finally an end marker. */
@ -4443,11 +4504,8 @@ module
module_port_list_opt
module_attribute_foreign ';'
{ 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!
pform_check_timeunit_prec();
}
timeunits_declaration_opt
{ pform_set_scope_timescale(@2); }
module_item_list_opt
module_end
{ Module::UCDriveType ucd;
@ -4484,8 +4542,6 @@ module
}
}
pform_endmodule($4, in_celldefine, ucd);
have_timeunit_decl = false; // We will allow decls again.
have_timeprec_decl = false;
}
endlabel_opt
{ // Last step: check any closing name. This is done late so
@ -4839,9 +4895,8 @@ module_item
| attribute_list_opt
IDENTIFIER parameter_value_opt gate_instance_list ';'
{ perm_string tmp1 = lex_strings.make($2);
pform_make_modgates(@2, tmp1, $3, $4);
pform_make_modgates(@2, tmp1, $3, $4, $1);
delete[]$2;
if ($1) delete $1;
}
| attribute_list_opt
@ -4864,6 +4919,18 @@ module_item
{ PProcess*tmp = pform_make_behavior(IVL_PR_ALWAYS, $3, $1);
FILE_NAME(tmp, @2);
}
| attribute_list_opt K_always_comb statement_item
{ PProcess*tmp = pform_make_behavior(IVL_PR_ALWAYS_COMB, $3, $1);
FILE_NAME(tmp, @2);
}
| attribute_list_opt K_always_ff statement_item
{ PProcess*tmp = pform_make_behavior(IVL_PR_ALWAYS_FF, $3, $1);
FILE_NAME(tmp, @2);
}
| attribute_list_opt K_always_latch statement_item
{ PProcess*tmp = pform_make_behavior(IVL_PR_ALWAYS_LATCH, $3, $1);
FILE_NAME(tmp, @2);
}
| attribute_list_opt K_initial statement_item
{ PProcess*tmp = pform_make_behavior(IVL_PR_INITIAL, $3, $1);
FILE_NAME(tmp, @2);
@ -4878,6 +4945,8 @@ module_item
| attribute_list_opt assertion_item
| timeunits_declaration
| class_declaration
| task_declaration
@ -5001,14 +5070,6 @@ module_item
| KK_attribute '(' error ')' ';'
{ yyerror(@1, "error: Malformed $attribute parameter list."); }
| K_timeunit_check TIME_LITERAL ';'
{ pform_set_timeunit($2, true, true); }
| K_timeunit_check TIME_LITERAL '/' TIME_LITERAL ';'
{ pform_set_timeunit($2, true, true);
pform_set_timeprecision($4, true, true);
}
| K_timeprecision_check TIME_LITERAL ';'
{ pform_set_timeprecision($2, true, true); }
;
module_item_list
@ -6241,6 +6302,8 @@ statement_item /* This is roughly statement_item in the LRM */
$$ = tmp;
}
| procedural_assertion_statement { $$ = $1; }
| loop_statement { $$ = $1; }
| jump_statement { $$ = $1; }
@ -6417,7 +6480,7 @@ statement_item /* This is roughly statement_item in the LRM */
$$ = tmp;
}
| K_wait K_fork ';'
{ PEventStatement*tmp = new PEventStatement(0);
{ PEventStatement*tmp = new PEventStatement((PEEvent*)0);
FILE_NAME(tmp,@1);
$$ = tmp;
}

View File

@ -1,7 +1,7 @@
#ifndef IVL_parse_api_H
#define IVL_parse_api_H
/*
* Copyright (c) 2001-2014 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-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
@ -42,28 +42,21 @@ struct enum_type_t;
*/
extern std::map<perm_string,Module*> pform_modules;
extern std::map<perm_string,PUdp*> pform_primitives;
extern std::map<perm_string,data_type_t*> pform_typedefs;
extern std::set<enum_type_t*> pform_enum_sets;
extern std::map<perm_string,PTaskFunc*> pform_tasks;
extern std::map<perm_string,PClass*> pform_classes;
extern std::vector<PPackage*> pform_units;
extern std::map<perm_string,PPackage*> pform_packages;
extern void pform_dump(std::ostream&out, const PClass*pac);
extern void pform_dump(std::ostream&out, const PPackage*pac);
extern void pform_dump(std::ostream&out, const PTaskFunc*tf);
extern void elaborate_rootscope_enumerations(Design*des);
extern void elaborate_rootscope_classes(Design*des);
extern void elaborate_rootscope_tasks(Design*des);
/*
* This code actually invokes the parser to make modules. The first
* parameter is the name of the file that is to be parsed. The
* optional second parameter is the opened descriptor for the file. If
* the descriptor is 0 (or skipped) then the function will attempt to
* open the file on its own.
* This code actually invokes the parser to make modules. If the path
* parameter is "-", the parser reads from stdin, otherwise it attempts
* to open and read the specified file. When reading from a file, if
* the ivlpp_string variable is not set to null, the file will be piped
* through the command specified by ivlpp_string before being parsed.
*/
extern int pform_parse(const char*path, FILE*file =0);
extern int pform_parse(const char*path);
extern string vl_file;

View File

@ -1,7 +1,7 @@
#ifndef IVL_parse_misc_H
#define IVL_parse_misc_H
/*
* Copyright (c) 1998-2014 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-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
@ -71,12 +71,6 @@ extern unsigned long based_size;
extern bool in_celldefine;
enum UCDriveType { UCD_NONE, UCD_PULL0, UCD_PULL1 };
extern UCDriveType uc_drive;
/*
* Flags to control if we are declaring or checking a timeunit or
* timeprecision statement.
*/
extern bool have_timeunit_decl;
extern bool have_timeprec_decl;
/*
* The parser signals back to the lexor that the next identifier

813
pform.cc

File diff suppressed because it is too large Load Diff

29
pform.h
View File

@ -1,7 +1,7 @@
#ifndef IVL_pform_H
#define IVL_pform_H
/*
* Copyright (c) 1998-2016 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-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
@ -147,7 +147,11 @@ extern bool pform_in_interface(void);
*/
extern PWire* pform_get_wire_in_scope(perm_string name);
extern PWire* pform_get_make_wire_in_scope(perm_string name, NetNet::Type net_type, NetNet::PortType port_type, ivl_variable_type_t vt_type);
extern PWire* pform_get_make_wire_in_scope(const struct vlltype&li,
perm_string name,
NetNet::Type net_type,
NetNet::PortType port_type,
ivl_variable_type_t vt_type);
/*
* The parser uses startmodule and endmodule together to build up a
@ -165,8 +169,8 @@ 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*>*);
extern void pform_set_scope_timescale(const struct vlltype&loc);
/* 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
@ -386,11 +390,11 @@ extern void pform_set_reg_idx(perm_string name,
extern void pform_set_data_type(const struct vlltype&li, data_type_t*, list<perm_string>*names, NetNet::Type net_type, list<named_pexpr_t>*attr);
extern void pform_set_struct_type(struct_type_t*struct_type, std::list<perm_string>*names, NetNet::Type net_type, std::list<named_pexpr_t>*attr);
extern void pform_set_struct_type(const struct vlltype&li, struct_type_t*struct_type, std::list<perm_string>*names, NetNet::Type net_type, std::list<named_pexpr_t>*attr);
extern void pform_set_string_type(const string_type_t*string_type, std::list<perm_string>*names, NetNet::Type net_type, std::list<named_pexpr_t>*attr);
extern void pform_set_string_type(const struct vlltype&li, const string_type_t*string_type, std::list<perm_string>*names, NetNet::Type net_type, std::list<named_pexpr_t>*attr);
extern void pform_set_class_type(class_type_t*class_type, std::list<perm_string>*names, NetNet::Type net_type, std::list<named_pexpr_t>*addr);
extern void pform_set_class_type(const struct vlltype&li, class_type_t*class_type, std::list<perm_string>*names, NetNet::Type net_type, std::list<named_pexpr_t>*addr);
/* pform_set_attrib and pform_set_type_attrib exist to support the
@ -478,7 +482,8 @@ extern void pform_makegates(const struct vlltype&loc,
extern void pform_make_modgates(const struct vlltype&loc,
perm_string type,
struct parmvalue_t*overrides,
svector<lgate>*gates);
svector<lgate>*gates,
list<named_pexpr_t>*attr);
/* Make a continuous assignment node, with optional bit- or part- select. */
extern void pform_make_pgassign_list(list<PExpr*>*alist,
@ -566,8 +571,12 @@ extern void parm_to_defparam_list(const string&param);
*/
extern bool get_time_unit(const char*cp, int &unit);
extern int pform_get_timeunit();
extern void pform_set_timeunit(const char*txt, bool in_module, bool only_check);
extern void pform_set_timeprecision(const char*txt, bool in_module,
bool only_check);
extern void pform_set_timeunit(const char*txt, bool initial_decl);
extern void pform_set_timeprec(const char*txt, bool initial_decl);
/*
* Flags to determine whether this is an initial declaration.
*/
extern bool allow_timeunit_decl;
extern bool allow_timeprec_decl;
#endif /* IVL_pform_H */

View File

@ -22,18 +22,18 @@
# include "parse_misc.h"
# include "ivl_assert.h"
static void pform_set_class_type(class_type_t*class_type, perm_string name, NetNet::Type net_type, list<named_pexpr_t>*attr)
static void pform_set_class_type(const struct vlltype&li, class_type_t*class_type, perm_string name, NetNet::Type net_type, list<named_pexpr_t>*attr)
{
PWire*net = pform_get_make_wire_in_scope(name, net_type, NetNet::NOT_A_PORT, IVL_VT_CLASS);
PWire*net = pform_get_make_wire_in_scope(li, name, net_type, NetNet::NOT_A_PORT, IVL_VT_CLASS);
assert(net);
net->set_data_type(class_type);
pform_bind_attributes(net->attributes, attr, true);
}
void pform_set_class_type(class_type_t*class_type, list<perm_string>*names, NetNet::Type net_type, list<named_pexpr_t>*attr)
void pform_set_class_type(const struct vlltype&li, class_type_t*class_type, list<perm_string>*names, NetNet::Type net_type, list<named_pexpr_t>*attr)
{
for (list<perm_string>::iterator cur = names->begin()
; cur != names->end() ; ++ cur) {
pform_set_class_type(class_type, *cur, net_type, attr);
pform_set_class_type(li, class_type, *cur, net_type, attr);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2016 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-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
@ -121,6 +121,15 @@ std::ostream& operator << (std::ostream&out, ivl_process_type_t pt)
case IVL_PR_ALWAYS:
out << "always";
break;
case IVL_PR_ALWAYS_COMB:
out << "always_comb";
break;
case IVL_PR_ALWAYS_FF:
out << "always_ff";
break;
case IVL_PR_ALWAYS_LATCH:
out << "always_latch";
break;
case IVL_PR_FINAL:
out << "final";
break;
@ -627,10 +636,10 @@ void PGBuiltin::dump(ostream&out, unsigned ind) const
out << "bufif1 ";
break;
case PGBuiltin::NOTIF0:
out << "bufif0 ";
out << "notif0 ";
break;
case PGBuiltin::NOTIF1:
out << "bufif1 ";
out << "notif1 ";
break;
case PGBuiltin::NAND:
out << "nand ";
@ -729,6 +738,7 @@ void PGModule::dump(ostream&out, unsigned ind) const
dump_pins(out);
}
out << ");" << endl;
dump_attributes_map(out, attributes, 8);
}
void Statement::dump(ostream&out, unsigned ind) const
@ -843,7 +853,7 @@ void PCase::dump(ostream&out, unsigned ind) const
for (unsigned idx = 0 ; idx < items_->count() ; idx += 1) {
PCase::Item*cur = (*items_)[idx];
if (cur->expr.size()) {
if (! cur->expr.empty()) {
out << setw(ind+2) << "" << "default:";
} else {
@ -1175,6 +1185,11 @@ void AProcess::dump(ostream&out, unsigned ind) const
case IVL_PR_ALWAYS:
out << setw(ind) << "" << "analog";
break;
case IVL_PR_ALWAYS_COMB:
case IVL_PR_ALWAYS_FF:
case IVL_PR_ALWAYS_LATCH:
assert(0);
break;
case IVL_PR_FINAL:
out << setw(ind) << "" << "analog final";
break;
@ -1705,8 +1720,10 @@ void PPackage::pform_dump(std::ostream&out) const
dump_localparams_(out, 4);
dump_parameters_(out, 4);
dump_enumerations_(out, 4);
dump_wires_(out, 4);
dump_tasks_(out, 4);
dump_funcs_(out, 4);
dump_var_inits_(out, 4);
out << "endpackage" << endl;
}

View File

@ -153,6 +153,11 @@ void pform_package_import(const struct vlltype&, PPackage*pkg, const char*ident)
scope->imports[cur->first] = pkg;
}
for (set<enum_type_t*>::const_iterator cur = pkg->enum_sets.begin()
; cur != pkg->enum_sets.end() ; ++ cur) {
scope->enum_sets.insert(*cur);
}
}
}

View File

@ -21,18 +21,17 @@
# include "parse_misc.h"
# include "ivl_assert.h"
static void pform_set_string_type(const string_type_t*, perm_string name, NetNet::Type net_type, list<named_pexpr_t>*attr)
static void pform_set_string_type(const struct vlltype&li, const string_type_t*, perm_string name, NetNet::Type net_type, list<named_pexpr_t>*attr)
{
PWire*net = pform_get_make_wire_in_scope(name, net_type, NetNet::NOT_A_PORT, IVL_VT_STRING);
PWire*net = pform_get_make_wire_in_scope(li, name, net_type, NetNet::NOT_A_PORT, IVL_VT_STRING);
assert(net);
pform_bind_attributes(net->attributes, attr, true);
}
void pform_set_string_type(const string_type_t*string_type, list<perm_string>*names, NetNet::Type net_type, list<named_pexpr_t>*attr)
void pform_set_string_type(const struct vlltype&li, const string_type_t*string_type, list<perm_string>*names, NetNet::Type net_type, list<named_pexpr_t>*attr)
{
for (list<perm_string>::iterator cur = names->begin()
; cur != names->end() ; ++ cur) {
pform_set_string_type(string_type, *cur, net_type, attr);
pform_set_string_type(li, string_type, *cur, net_type, attr);
}
}

View File

@ -62,20 +62,20 @@ ivl_variable_type_t struct_type_t::figure_packed_base_type(void) const
* out the base type of the packed variable. Elaboration, later on,
* well figure out the rest.
*/
static void pform_set_packed_struct(struct_type_t*struct_type, perm_string name, NetNet::Type net_type, list<named_pexpr_t>*attr)
static void pform_set_packed_struct(const struct vlltype&li, struct_type_t*struct_type, perm_string name, NetNet::Type net_type, list<named_pexpr_t>*attr)
{
ivl_variable_type_t base_type = struct_type->figure_packed_base_type();
PWire*net = pform_get_make_wire_in_scope(name, net_type, NetNet::NOT_A_PORT, base_type);
PWire*net = pform_get_make_wire_in_scope(li, name, net_type, NetNet::NOT_A_PORT, base_type);
assert(net);
net->set_data_type(struct_type);
pform_bind_attributes(net->attributes, attr, true);
}
static void pform_set_struct_type(struct_type_t*struct_type, perm_string name, NetNet::Type net_type, list<named_pexpr_t>*attr)
static void pform_set_struct_type(const struct vlltype&li, struct_type_t*struct_type, perm_string name, NetNet::Type net_type, list<named_pexpr_t>*attr)
{
if (struct_type->packed_flag) {
pform_set_packed_struct(struct_type, name, net_type, attr);
pform_set_packed_struct(li, struct_type, name, net_type, attr);
return;
}
@ -83,11 +83,11 @@ static void pform_set_struct_type(struct_type_t*struct_type, perm_string name, N
// a "sorry" message, so no need to do anything here.
}
void pform_set_struct_type(struct_type_t*struct_type, list<perm_string>*names, NetNet::Type net_type, list<named_pexpr_t>*attr)
void pform_set_struct_type(const struct vlltype&li, struct_type_t*struct_type, list<perm_string>*names, NetNet::Type net_type, list<named_pexpr_t>*attr)
{
for (list<perm_string>::iterator cur = names->begin()
; cur != names->end() ; ++ cur) {
pform_set_struct_type(struct_type, *cur, net_type, attr);
pform_set_struct_type(li, struct_type, *cur, net_type, attr);
}
}
@ -99,7 +99,7 @@ static void pform_makewire(const struct vlltype&li,
{
ivl_variable_type_t base_type = struct_type->figure_packed_base_type();
PWire*cur = pform_get_make_wire_in_scope(name, NetNet::WIRE, ptype, base_type);
PWire*cur = pform_get_make_wire_in_scope(li, name, NetNet::WIRE, ptype, base_type);
assert(cur);
FILE_NAME(cur, li);
cur->set_data_type(struct_type);

View File

@ -1,7 +1,7 @@
#ifndef IVL_pform_types_H
#define IVL_pform_types_H
/*
* Copyright (c) 2007-2016 Stephen Williams (steve@icarus.com)
* Copyright (c) 2007-2018 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
@ -33,6 +33,10 @@
# include <map>
# include <memory>
#if __cplusplus < 201103L
#define unique_ptr auto_ptr
#endif
/*
* parse-form types.
*/
@ -117,7 +121,7 @@ struct name_component_t {
struct decl_assignment_t {
perm_string name;
std::list<pform_range_t>index;
std::auto_ptr<PExpr> expr;
std::unique_ptr<PExpr> expr;
};
struct pform_tf_port_t {
@ -170,14 +174,14 @@ struct enum_type_t : public data_type_t {
ivl_variable_type_t base_type;
bool signed_flag;
bool integer_flag; // True if "integer" was used
std::auto_ptr< list<pform_range_t> > range;
std::auto_ptr< list<named_pexpr_t> > names;
std::unique_ptr< list<pform_range_t> > range;
std::unique_ptr< list<named_pexpr_t> > names;
LineInfo li;
};
struct struct_member_t : public LineInfo {
std::auto_ptr<data_type_t> type;
std::auto_ptr< list<decl_assignment_t*> > names;
std::unique_ptr<data_type_t> type;
std::unique_ptr< list<decl_assignment_t*> > names;
void pform_dump(std::ostream&out, unsigned indent) const;
};
@ -188,7 +192,7 @@ struct struct_type_t : public data_type_t {
bool packed_flag;
bool union_flag;
std::auto_ptr< list<struct_member_t*> > members;
std::unique_ptr< list<struct_member_t*> > members;
};
struct atom2_type_t : public data_type_t {
@ -234,7 +238,7 @@ struct vector_type_t : public data_type_t {
bool reg_flag; // True if "reg" was used
bool integer_flag; // True if "integer" was used
bool implicit_flag; // True if this type is implicitly logic/reg
std::auto_ptr< list<pform_range_t> > pdims;
std::unique_ptr< list<pform_range_t> > pdims;
};
struct array_base_t : public data_type_t {
@ -243,7 +247,7 @@ struct array_base_t : public data_type_t {
: base_type(btype), dims(pd) { }
data_type_t*base_type;
std::auto_ptr< list<pform_range_t> > dims;
std::unique_ptr< list<pform_range_t> > dims;
};
/*
@ -376,4 +380,8 @@ extern std::ostream& operator<< (std::ostream&out, const pform_name_t&);
extern std::ostream& operator<< (std::ostream&out, const name_component_t&that);
extern std::ostream& operator<< (std::ostream&out, const index_component_t&that);
#if __cplusplus < 201103L
#undef unique_ptr
#endif
#endif /* IVL_pform_types_H */

View File

@ -1,7 +1,7 @@
#ifndef IVL_svector_H
#define IVL_svector_H
/*
* Copyright (c) 1999-2014 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-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
@ -57,7 +57,7 @@ template <class TYPE> class svector {
items_[l.nitems_+idx] = r[idx];
}
svector(const svector<TYPE>&l, TYPE r)
svector(const svector<TYPE>&l, TYPE&r)
: nitems_(l.nitems_ + 1), items_(new TYPE[nitems_])
{ for (unsigned idx = 0 ; idx < l.nitems_ ; idx += 1)
items_[idx] = l[idx];

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003-2015 Stephen Williams (steve@icarus.com)
* Copyright (c) 2003-2017 Stephen Williams (steve@icarus.com)
* Copyright CERN 2012 / Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
@ -143,14 +143,21 @@ static bool symbol_search(const LineInfo*li, Design*des, NetScope*scope,
}
}
// Don't scan up past a module boundary.
if (scope->type()==NetScope::MODULE && !scope->nested_module())
break;
// Don't scan up if we are searching within a prefixed scope.
if (prefix_scope)
break;
scope = scope->parent();
// Don't scan up past a module boundary.
if (scope->type()==NetScope::MODULE && !scope->nested_module())
scope = 0;
else
scope = scope->parent();
// Last chance - try the compilation unit.
if (scope == 0 && start_scope != 0) {
scope = start_scope->unit();
start_scope = 0;
}
}
// Last chance: this is a single name, so it might be the name

View File

@ -1,7 +1,7 @@
%{
/*
* Copyright (c) 2000-2015 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
@ -304,6 +304,15 @@ static void syn_start_process(NetProcTop*t)
last_ = first_;
ptr_ = first_;
// Can the following be converted into S_ALWAYS?
if ((t->type() == IVL_PR_ALWAYS_COMB) ||
(t->type() == IVL_PR_ALWAYS_FF) ||
(t->type() == IVL_PR_ALWAYS_LATCH)) {
cerr << t->get_fileline() << ": internal error: "
<< " Need to check if this can be synthesized." << endl;
assert(0);
}
first_->token = (t->type() == IVL_PR_ALWAYS)? S_ALWAYS : S_INITIAL;
first_->top = t;
first_->next_ = 0;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2012 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-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
@ -134,6 +134,9 @@ void synth_f::process(Design*des, NetProcTop*top)
top_ = top;
switch (top->type()) {
case IVL_PR_ALWAYS:
case IVL_PR_ALWAYS_COMB:
case IVL_PR_ALWAYS_FF:
case IVL_PR_ALWAYS_LATCH:
proc_always_(des);
break;
case IVL_PR_INITIAL:

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2016 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2018 Stephen Williams (steve@icarus.com)
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
* Copyright (c) 2016 CERN Michele Castellana (michele.castellana@cern.ch)
*
@ -93,10 +93,7 @@ extern "C" void ivl_design_roots(ivl_design_t des, ivl_scope_t **scopes,
assert (nscopes && scopes);
if (des->root_scope_list.size() == 0) {
size_t fill = 0;
des->root_scope_list.resize(des->root_tasks.size() + des->packages.size() + des->roots.size() + des->classes.size());
for (map<const NetScope*,ivl_scope_t>::iterator idx = des->root_tasks.begin()
; idx != des->root_tasks.end() ; ++ idx)
des->root_scope_list[fill++] = idx->second;
des->root_scope_list.resize(des->packages.size() + des->roots.size() + des->classes.size());
for (map<const NetScope*,ivl_scope_t>::iterator idx = des->classes.begin()
; idx != des->classes.end() ; ++ idx)
@ -1238,6 +1235,8 @@ extern "C" ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx)
case IVL_LPM_CMP_GT:
case IVL_LPM_CMP_NE:
case IVL_LPM_CMP_NEE:
case IVL_LPM_CMP_WEQ:
case IVL_LPM_CMP_WNE:
case IVL_LPM_DIVIDE:
case IVL_LPM_MOD:
case IVL_LPM_MULT:
@ -1393,6 +1392,8 @@ extern "C" ivl_nexus_t ivl_lpm_q(ivl_lpm_t net)
case IVL_LPM_CMP_EQX:
case IVL_LPM_CMP_EQZ:
case IVL_LPM_CMP_NEE:
case IVL_LPM_CMP_WEQ:
case IVL_LPM_CMP_WNE:
case IVL_LPM_DIVIDE:
case IVL_LPM_MOD:
case IVL_LPM_MULT:
@ -1519,6 +1520,7 @@ extern "C" unsigned ivl_lpm_selects(ivl_lpm_t net)
case IVL_LPM_CONCATZ:
cerr << "error: ivl_lpm_selects() is no longer supported for "
"IVL_LPM_CONCAT, use ivl_lpm_size() instead." << endl;
// fallthrough
default:
assert(0);
return 0;
@ -1543,6 +1545,8 @@ extern "C" int ivl_lpm_signed(ivl_lpm_t net)
case IVL_LPM_CMP_GT:
case IVL_LPM_CMP_NE:
case IVL_LPM_CMP_NEE:
case IVL_LPM_CMP_WEQ:
case IVL_LPM_CMP_WNE:
case IVL_LPM_DIVIDE:
case IVL_LPM_MOD:
case IVL_LPM_MULT:
@ -2134,7 +2138,7 @@ extern "C" int ivl_scope_func_signed(ivl_scope_t net)
assert(net);
assert(net->type_==IVL_SCT_FUNCTION);
assert(net->func_type==IVL_VT_LOGIC || net->func_type==IVL_VT_BOOL);
return net->func_signed? !0 : 0;
return net->func_signed? 1 : 0;
}
extern "C" unsigned ivl_scope_func_width(ivl_scope_t net)
@ -2812,6 +2816,16 @@ extern "C" uint64_t ivl_stmt_delay_val(ivl_statement_t net)
return net->u_.delay_.value;
}
extern "C" unsigned ivl_stmt_needs_t0_trigger(ivl_statement_t net)
{
assert(net);
if (net->type_ == IVL_ST_WAIT) {
return net->u_.wait_.needs_t0_trigger;
} else {
return 0;
}
}
extern "C" unsigned ivl_stmt_nevent(ivl_statement_t net)
{
assert(net);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2013 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
@ -847,12 +847,15 @@ bool dll_target::proc_wait(const NetEvWait*net)
/* This is a wait fork statement. */
if ((net->nevents() == 1) && (net->event(0) == 0)) {
stmt_cur_->u_.wait_.needs_t0_trigger = 0;
stmt_cur_->u_.wait_.event = 0;
stmt_cur_->type_ = IVL_ST_WAIT;
stmt_cur_->u_.wait_.stmt_->type_ = IVL_ST_NOOP;
return true;
}
stmt_cur_->u_.wait_.needs_t0_trigger = net->has_t0_trigger();
// This event processing code is also in the NB assign above.
if (net->nevents() > 1) {
stmt_cur_->u_.wait_.events = (ivl_event_t*)

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2016 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2018 Stephen Williams (steve@icarus.com)
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
@ -261,12 +261,6 @@ ivl_scope_t dll_target::find_scope(ivl_design_s &des, const NetScope*cur)
return tmp;
}
if (cur->type()==NetScope::TASK || cur->type()==NetScope::FUNC) {
map<const NetScope*,ivl_scope_t>::const_iterator idx = des.root_tasks.find(cur);
if (idx != des.root_tasks.end())
return idx->second;
}
for (unsigned idx = 0; idx < des.roots.size(); idx += 1) {
assert(des.roots[idx]);
ivl_scope_t scope = find_scope_from_root(des.roots[idx], cur);
@ -650,22 +644,6 @@ void dll_target::add_root(const NetScope *s)
case NetScope::CLASS:
root_->type_ = IVL_SCT_CLASS;
break;
case NetScope::TASK: {
const NetTaskDef*def = s->task_def();
if (def == 0) {
cerr << "?:?" << ": internal error: "
<< "task " << root_->name_
<< " has no definition." << endl;
}
assert(def);
root_->type_ = IVL_SCT_TASK;
root_->tname_ = def->scope()->basename();
break;
}
break;
case NetScope::FUNC:
fill_in_scope_function(root_, s);
break;
default:
assert(0);
}
@ -694,11 +672,6 @@ void dll_target::add_root(const NetScope *s)
des_.classes[s] = root_;
break;
case NetScope::TASK:
case NetScope::FUNC:
des_.root_tasks[s] = root_;
break;
default:
assert(0);
break;
@ -740,11 +713,7 @@ bool dll_target::start_design(const Design*des)
}
assert(idx == des_.disciplines.size());
list<NetScope *> scope_list = des->find_roottask_scopes();
for (list<NetScope*>::const_iterator cur = scope_list.begin()
; cur != scope_list.end() ; ++ cur) {
add_root(*cur);
}
list<NetScope *> scope_list;
scope_list = des->find_package_scopes();
for (list<NetScope*>::const_iterator cur = scope_list.begin()
@ -1275,6 +1244,12 @@ void dll_target::net_case_cmp(const NetCaseCmp*net)
case NetCaseCmp::NEQ:
obj->type = IVL_LPM_CMP_NEE;
break;
case NetCaseCmp::WEQ:
obj->type = IVL_LPM_CMP_WEQ;
break;
case NetCaseCmp::WNE:
obj->type = IVL_LPM_CMP_WNE;
break;
case NetCaseCmp::XEQ:
obj->type = IVL_LPM_CMP_EQX;
break;
@ -2544,6 +2519,7 @@ void dll_target::scope(const NetScope*net)
case NetScope::PACKAGE:
cerr << "?:?" << ": internal error: "
<< "Package scopes should not have parents." << endl;
// fallthrough
case NetScope::MODULE:
scop->type_ = IVL_SCT_MODULE;
scop->tname_ = net->module_name();

View File

@ -1,7 +1,7 @@
#ifndef IVL_t_dll_H
#define IVL_t_dll_H
/*
* Copyright (c) 2000-2016 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
@ -645,7 +645,7 @@ struct ivl_parameter_s {
* that generally only matters for VPI calls.
*/
struct ivl_process_s {
ivl_process_type_t type_ : 2;
ivl_process_type_t type_ : 3;
unsigned int analog_flag : 1;
ivl_scope_t scope_;
ivl_statement_t stmt_;
@ -862,6 +862,7 @@ struct ivl_statement_s {
} utask_;
struct { /* IVL_ST_TRIGGER IVL_ST_WAIT */
unsigned needs_t0_trigger;
unsigned nevent;
union {
ivl_event_t event;

View File

@ -6,7 +6,7 @@
%{
/*
* Copyright (C) 2011-2013 Stephen Williams (steve@icarus.com)
* Copyright (C) 2011-2017 Stephen Williams (steve@icarus.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
@ -79,11 +79,14 @@ void init_fp_lexor(FILE*fd)
yyrestart(fd);
}
/*
* Modern version of flex (>=2.5.9) can clean up the scanner data.
*/
void destroy_fp_lexor()
{
# ifdef FLEX_SCANNER
# if YY_FLEX_MAJOR_VERSION >= 2 && YY_FLEX_MINOR_VERSION >= 5
# if defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9
# if YY_FLEX_MINOR_VERSION > 5 || defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9
yylex_destroy();
# endif
# endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2016 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
@ -394,6 +394,12 @@ static void show_lpm_cmp_eeq(ivl_lpm_t net)
case IVL_LPM_CMP_NEE:
str = "NEE";
break;
case IVL_LPM_CMP_WEQ:
str = "WEQ";
break;
case IVL_LPM_CMP_WNE:
str = "WNE";
break;
default:
assert(0);
break;
@ -1043,6 +1049,8 @@ static void show_lpm(ivl_lpm_t net)
case IVL_LPM_CMP_EQX:
case IVL_LPM_CMP_EQZ:
case IVL_LPM_CMP_NEE:
case IVL_LPM_CMP_WEQ:
case IVL_LPM_CMP_WNE:
show_lpm_cmp_eeq(net);
break;
@ -1158,6 +1166,24 @@ static int show_process(ivl_process_t net, void*x)
else
fprintf(out, "always\n");
break;
case IVL_PR_ALWAYS_COMB:
if (ivl_process_analog(net))
assert(0);
else
fprintf(out, "always_comb\n");
break;
case IVL_PR_ALWAYS_FF:
if (ivl_process_analog(net))
assert(0);
else
fprintf(out, "always_ff\n");
break;
case IVL_PR_ALWAYS_LATCH:
if (ivl_process_analog(net))
assert(0);
else
fprintf(out, "always_latch\n");
break;
case IVL_PR_FINAL:
if (ivl_process_analog(net))
fprintf(out, "analog final\n");

View File

@ -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
@ -393,6 +393,9 @@ static int show_process(ivl_process_t net, void*x)
fprintf(out, " initial\n");
break;
case IVL_PR_ALWAYS:
case IVL_PR_ALWAYS_COMB:
case IVL_PR_ALWAYS_FF:
case IVL_PR_ALWAYS_LATCH:
fprintf(out, " always\n");
break;
case IVL_PR_FINAL:

View File

@ -1,7 +1,7 @@
/*
* VHDL code generation for statements.
*
* Copyright (C) 2008-2013 Nick Gasson (nick@nickg.me.uk)
* Copyright (C) 2008-2018 Nick Gasson (nick@nickg.me.uk)
*
* 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
@ -683,8 +683,10 @@ static void get_nexuses_from_expr(ivl_expr_t expr, set<ivl_nexus_t> &out)
break;
case IVL_EX_TERNARY:
get_nexuses_from_expr(ivl_expr_oper3(expr), out);
// fallthrough
case IVL_EX_BINARY:
get_nexuses_from_expr(ivl_expr_oper2(expr), out);
// fallthrough
case IVL_EX_UNARY:
get_nexuses_from_expr(ivl_expr_oper1(expr), out);
break;
@ -1248,6 +1250,7 @@ static void process_number(vhdl_binop_expr *all, vhdl_var_ref *test,
switch (bits[i]) {
case 'x':
if (is_casez) break;
// fallthrough
case '?':
case 'z':
continue; // Ignore these.

View File

@ -108,7 +108,7 @@ void vhdl_element::print() const
// Trap allocations of vhdl_element subclasses.
// This records the pointer allocated in a static field of vhdl_element
// so we can delete it just before the code generator exits.
void* vhdl_element::operator new(size_t size) throw (bad_alloc)
void* vhdl_element::operator new(size_t size)
{
// Let the default new handle the allocation
void* ptr = ::operator new(size);
@ -171,4 +171,3 @@ int vhdl_element::free_all_objects()
return freed;
}

View File

@ -46,7 +46,7 @@ class vhdl_element {
public:
virtual ~vhdl_element() {}
void* operator new(size_t size) throw (std::bad_alloc);
void* operator new(size_t size);
void operator delete(void* ptr);
virtual void emit(std::ostream &of, int level=0) const = 0;
@ -74,4 +74,3 @@ std::string nl_string(int level);
void blank_line(std::ostream &of, int level);
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2011-2013 Cary R. (cygcary@yahoo.com)
* Copyright (C) 2011-2017 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
@ -21,6 +21,24 @@
# include "config.h"
# include "vlog95_priv.h"
static unsigned need_ivl_top_module = 0;
void emit_icarus_generated_top_module()
{
if (need_ivl_top_module) {
fprintf(vlog_out,
"\n"
"/*\n"
" * This module is used to trigger any always_comb or always_latch processes\n"
" * at time zero to make sure all the outputs have the correct values.\n"
"*/\n"
"module IVL_top_priv_module;\n"
" event IVL_T0_trigger_event;\n"
" initial #0 -> IVL_T0_trigger_event;\n"
"endmodule /* IVL_top_priv_module */\n");
}
}
void emit_event(ivl_scope_t scope, ivl_statement_t stmt)
{
unsigned eidx, nevents, first = 1;
@ -68,4 +86,12 @@ void emit_event(ivl_scope_t scope, ivl_statement_t stmt)
emit_id(ivl_event_basename(event));
}
}
/* If this is an always_comb/latch then we need to add a trigger to
* get the correct functionality. */
if (ivl_stmt_needs_t0_trigger(stmt)) {
assert(first == 0);
fprintf(vlog_out, " or IVL_top_priv_module.IVL_T0_trigger_event");
need_ivl_top_module = 1;
};
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2011-2014 Cary R. (cygcary@yahoo.com)
* Copyright (C) 2011-2018 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
@ -44,8 +44,10 @@ static expr_sign_t expr_get_binary_sign_type(ivl_expr_t expr)
switch (ivl_expr_opcode(expr)) {
case 'E':
case 'e':
case 'w':
case 'N':
case 'n':
case 'W':
case '<':
case 'L':
case '>':
@ -417,8 +419,10 @@ static void emit_expr_binary(ivl_scope_t scope, ivl_expr_t expr, unsigned wid,
case 'p': oper = "**"; break;
case 'E': oper = "==="; break;
case 'e': oper = "=="; break;
case 'w': oper = "==?"; break;
case 'N': oper = "!=="; break;
case 'n': oper = "!="; break;
case 'W': oper = "!=?"; break;
case '<': oper = "<"; break;
case 'L': oper = "<="; break;
case '>': oper = ">"; break;
@ -447,6 +451,7 @@ static void emit_expr_binary(ivl_scope_t scope, ivl_expr_t expr, unsigned wid,
ivl_expr_file(expr), ivl_expr_lineno(expr));
vlog_errors += 1;
}
//fallthrough
case '+':
case '-':
case '*':
@ -465,6 +470,14 @@ static void emit_expr_binary(ivl_scope_t scope, ivl_expr_t expr, unsigned wid,
fprintf(vlog_out, " %s ", oper);
emit_expr(scope, oper2, wid, 0, can_skip_unsigned, is_full_prec);
break;
case 'w':
case 'W':
fprintf(stderr, "%s:%u: vlog95 error: The wild equality operators "
"cannot be converted.\n",
ivl_expr_file(expr),
ivl_expr_lineno(expr));
vlog_errors += 1;
// fallthrough
case 'E':
case 'e':
case 'N':
@ -492,6 +505,7 @@ static void emit_expr_binary(ivl_scope_t scope, ivl_expr_t expr, unsigned wid,
ivl_expr_file(expr), ivl_expr_lineno(expr));
vlog_errors += 1;
}
// fallthrough
case 'l':
case 'r':
emit_expr(scope, oper1, wid, 0, 0, 0);

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2011-2016 Cary R. (cygcary@yahoo.com)
* Copyright (C) 2011-2018 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
@ -398,6 +398,8 @@ static ivl_nexus_t get_lpm_output(ivl_scope_t scope, ivl_lpm_t lpm)
case IVL_LPM_CMP_GT:
case IVL_LPM_CMP_NE:
case IVL_LPM_CMP_NEE:
case IVL_LPM_CMP_WEQ:
case IVL_LPM_CMP_WNE:
case IVL_LPM_CONCAT:
case IVL_LPM_CONCATZ:
case IVL_LPM_DIVIDE:
@ -1194,19 +1196,19 @@ static void emit_lpm_as_ca(ivl_scope_t scope, ivl_lpm_t lpm,
fprintf(vlog_out, ")");
break;
case IVL_LPM_CMP_EQX:
// HERE: Need to heck that this is not a real nexus.
// HERE: Need to check that this is not a real nexus.
fprintf(vlog_out, "(");
emit_nexus_as_ca(scope, ivl_lpm_data(lpm, 0), 0, 0);
fprintf(vlog_out, " ==? ");
emit_nexus_as_ca(scope, ivl_lpm_data(lpm, 1), 0, 0);
fprintf(vlog_out, ")");
fprintf(stderr, "%s:%u: vlog95 error: Compare wildcard equal "
fprintf(stderr, "%s:%u: vlog95 error: Compare wildcard equal (caseX) "
"operator is not supported.\n",
ivl_lpm_file(lpm), ivl_lpm_lineno(lpm));
vlog_errors += 1;
break;
case IVL_LPM_CMP_EQZ:
// HERE: Need to heck that this is not a real nexus.
// HERE: Need to check that this is not a real nexus.
fprintf(vlog_out, "(");
emit_nexus_as_ca(scope, ivl_lpm_data(lpm, 0), 0, 0);
fprintf(vlog_out, " == ");
@ -1245,6 +1247,28 @@ static void emit_lpm_as_ca(ivl_scope_t scope, ivl_lpm_t lpm,
emit_nexus_as_ca(scope, ivl_lpm_data(lpm, 1), 0, 0);
fprintf(vlog_out, ")");
break;
case IVL_LPM_CMP_WEQ:
fprintf(vlog_out, "(");
emit_nexus_as_ca(scope, ivl_lpm_data(lpm, 0), 0, 0);
fprintf(vlog_out, " ==? ");
emit_nexus_as_ca(scope, ivl_lpm_data(lpm, 1), 0, 0);
fprintf(vlog_out, ")");
fprintf(stderr, "%s:%u: vlog95 error: Wild equality "
"operator is not supported.\n",
ivl_lpm_file(lpm), ivl_lpm_lineno(lpm));
vlog_errors += 1;
break;
case IVL_LPM_CMP_WNE:
fprintf(vlog_out, "(");
emit_nexus_as_ca(scope, ivl_lpm_data(lpm, 0), 0, 0);
fprintf(vlog_out, " !=? ");
emit_nexus_as_ca(scope, ivl_lpm_data(lpm, 1), 0, 0);
fprintf(vlog_out, ")");
fprintf(stderr, "%s:%u: vlog95 error: Wild inequality "
"operator is not supported.\n",
ivl_lpm_file(lpm), ivl_lpm_lineno(lpm));
vlog_errors += 1;
break;
/* A concat-Z should never be generated, but report it as an
* error if one is generated. */
case IVL_LPM_CONCATZ:
@ -1252,6 +1276,7 @@ static void emit_lpm_as_ca(ivl_scope_t scope, ivl_lpm_t lpm,
"should not be generated.\n",
ivl_lpm_file(lpm), ivl_lpm_lineno(lpm));
vlog_errors += 1;
// fallthrough
case IVL_LPM_CONCAT:
emit_lpm_concat(scope, lpm);
break;
@ -2429,10 +2454,9 @@ void dump_nexus_information(ivl_scope_t scope, ivl_nexus_t nex)
case IVL_VT_BOOL: fprintf(stderr, " bool"); break;
case IVL_VT_LOGIC: fprintf(stderr, " logic"); break;
case IVL_VT_STRING: fprintf(stderr, " string"); break;
case IVL_VT_DARRAY: fprintf(stderr, " dynamic array");
case IVL_VT_CLASS: fprintf(stderr, " class");
case IVL_VT_QUEUE: fprintf(stderr, " queue");
break;
case IVL_VT_DARRAY: fprintf(stderr, " dynamic array"); break;
case IVL_VT_CLASS: fprintf(stderr, " class"); break;
case IVL_VT_QUEUE: fprintf(stderr, " queue"); break;
}
if (ivl_signal_signed(sig)) fprintf(stderr, " <signed>");
} else fprintf(stderr, "Error: No/missing information!");

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2011-2014 Cary R. (cygcary@yahoo.com)
* Copyright (C) 2011-2017 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
@ -1606,6 +1606,9 @@ void emit_process(ivl_scope_t scope, ivl_process_t proc)
fprintf(vlog_out, "initial");
break;
case IVL_PR_ALWAYS:
case IVL_PR_ALWAYS_COMB:
case IVL_PR_ALWAYS_FF:
case IVL_PR_ALWAYS_LATCH:
fprintf(vlog_out, "always");
break;
case IVL_PR_FINAL:

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2010-2016 Cary R. (cygcary@yahoo.com)
* Copyright (C) 2010-2017 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-2015 Cary R. (cygcary@yahoo.com)\n\n"
"Copyright (C) 2010-2017 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"
@ -219,9 +219,12 @@ int target_design(ivl_design_t des)
/* Emit any UDP definitions that the design used. */
emit_udp_list();
/* Emit any UDPs that are Icarus generated (D-FF). */
/* Emit any UDPs that are Icarus generated (D-FF or latch). */
emit_icarus_generated_udps();
/* Emit the Icarus top module used to trigger translated always_comb/latch processes at T0. */
emit_icarus_generated_top_module();
/* If there were errors then add this information to the output. */
if (vlog_errors) {
fprintf(vlog_out, "\n");

View File

@ -1,7 +1,7 @@
#ifndef IVL_vlog95_priv_H
#define IVL_vlog95_priv_H
/*
* Copyright (C) 2010-2016 Cary R. (cygcary@yahoo.com)
* Copyright (C) 2010-2017 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
@ -106,7 +106,6 @@ extern void emit_nexus_as_ca(ivl_scope_t scope, ivl_nexus_t nex,
extern void emit_nexus_port_driver_as_ca(ivl_scope_t scope, ivl_nexus_t nex);
extern void emit_const_nexus(ivl_scope_t scope, ivl_net_const_t const_net);
extern void emit_signal_net_const_as_ca(ivl_scope_t scope, ivl_signal_t sig);
extern void emit_icarus_generated_udps(void);
extern void add_udp_to_list(ivl_udp_t udp);
extern void emit_udp_list(void);
@ -118,6 +117,9 @@ extern void emit_number(const char *bits, unsigned nbits, unsigned is_signed,
const char *file, unsigned lineno);
extern void emit_string(const char *string);
extern void emit_icarus_generated_udps(void);
extern void emit_icarus_generated_top_module(void);
/*
* Find the enclosing module scope.
*/

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2016 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-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
@ -398,6 +398,8 @@ static char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr)
case IVL_LPM_CONCATZ:
case IVL_LPM_CMP_EEQ:
case IVL_LPM_CMP_EQ:
case IVL_LPM_CMP_WEQ:
case IVL_LPM_CMP_WNE:
case IVL_LPM_CMP_EQX:
case IVL_LPM_CMP_EQZ:
case IVL_LPM_CMP_GE:

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008-2016 Stephen Williams (steve@icarus.com)
* Copyright (c) 2008-2018 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
@ -73,6 +73,15 @@ void draw_switch_in_scope(ivl_switch_t sw)
}
switch (ivl_switch_type(sw)) {
case IVL_SW_RTRAN:
fprintf(vvp_out, " .rtran");
break;
case IVL_SW_RTRANIF0:
fprintf(vvp_out, " .rtranif0");
break;
case IVL_SW_RTRANIF1:
fprintf(vvp_out, " .rtranif1");
break;
case IVL_SW_TRAN:
fprintf(vvp_out, " .tran");
break;
@ -88,8 +97,7 @@ void draw_switch_in_scope(ivl_switch_t sw)
break;
default:
fprintf(stderr, "%s:%u: tgt-vvp sorry: resistive switch modeling "
"is not currently supported.\n",
fprintf(stderr, "%s:%u: tgt-vvp error: unrecognised switch type.\n",
ivl_switch_file(sw), ivl_switch_lineno(sw));
vvp_errors += 1;
return;

View File

@ -82,6 +82,7 @@ static int eval_darray_new(ivl_expr_t ex)
unsigned idx;
switch (ivl_type_base(element_type)) {
case IVL_VT_BOOL:
case IVL_VT_LOGIC:
for (idx = 0 ; idx < ivl_expr_parms(init_expr) ; idx += 1) {
draw_eval_vec4(ivl_expr_parm(init_expr,idx));
fprintf(vvp_out, " %%ix/load 3, %u, 0;\n", idx);
@ -110,6 +111,11 @@ static int eval_darray_new(ivl_expr_t ex)
errors += 1;
break;
}
} else if (init_expr && (ivl_expr_value(init_expr) == IVL_VT_DARRAY)) {
ivl_signal_t sig = ivl_expr_signal(init_expr);
fprintf(vvp_out, " %%load/obj v%p_0;\n", sig);
fprintf(vvp_out, " %%scopy;\n");
} else if (init_expr && number_is_immediate(size_expr,32,0)) {
/* In this case, there is an init expression, the
expression is NOT an array_pattern, and the size

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003-2013 Stephen Williams (steve@icarus.com)
* Copyright (c) 2003-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
@ -57,6 +57,8 @@ static void draw_binary_real(ivl_expr_t expr)
switch (ivl_expr_opcode(expr)) {
case 'E':
case 'N':
case 'w':
case 'W':
case 'l':
case 'r':
case 'R':

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2015 Stephen Williams (steve@icarus.com)
* Copyright (c) 2013-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
@ -385,8 +385,7 @@ static void draw_binary_vec4_compare(ivl_expr_t expr)
fprintf(vvp_out, " %%flag_get/vec4 4;\n");
break;
case 'n': /* != */
fprintf(vvp_out, " %%cmp/e;\n");
fprintf(vvp_out, " %%flag_inv 4;\n");
fprintf(vvp_out, " %%cmp/ne;\n");
fprintf(vvp_out, " %%flag_get/vec4 4;\n");
break;
case 'E': /* === */
@ -394,10 +393,17 @@ static void draw_binary_vec4_compare(ivl_expr_t expr)
fprintf(vvp_out, " %%flag_get/vec4 6;\n");
break;
case 'N': /* !== */
fprintf(vvp_out, " %%cmp/e;\n");
fprintf(vvp_out, " %%flag_inv 6;\n");
fprintf(vvp_out, " %%cmp/ne;\n");
fprintf(vvp_out, " %%flag_get/vec4 6;\n");
break;
case 'w': /* ==? */
fprintf(vvp_out, " %%cmp/we;\n");
fprintf(vvp_out, " %%flag_get/vec4 4;\n");
break;
case 'W': /* !=? */
fprintf(vvp_out, " %%cmp/wne;\n");
fprintf(vvp_out, " %%flag_get/vec4 4;\n");
break;
default:
assert(0);
}
@ -689,8 +695,10 @@ static void draw_binary_vec4(ivl_expr_t expr)
case 'e': /* == */
case 'E': /* === */
case 'n': /* !== */
case 'n': /* != */
case 'N': /* !== */
case 'w': /* ==? */
case 'W': /* !=? */
draw_binary_vec4_compare(expr);
break;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2016 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-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
@ -1643,6 +1643,7 @@ static int show_stmt_utask(ivl_statement_t net)
static int show_stmt_wait(ivl_statement_t net, ivl_scope_t sscope)
{
static unsigned int cascade_counter = 0;
/* Look to see if this is a SystemVerilog wait fork. */
if ((ivl_stmt_nevent(net) == 1) && (ivl_stmt_events(net, 0) == 0)) {
assert(ivl_statement_type(ivl_stmt_sub_stmt(net)) == IVL_ST_NOOP);
@ -1655,11 +1656,17 @@ static int show_stmt_wait(ivl_statement_t net, ivl_scope_t sscope)
if (ivl_stmt_nevent(net) == 1) {
ivl_event_t ev = ivl_stmt_events(net, 0);
fprintf(vvp_out, " %%wait E_%p;\n", ev);
if (ivl_stmt_needs_t0_trigger(net)) {
fprintf(vvp_out, "Ewait_%u .event/or E_%p, E_0x0;\n",
cascade_counter, ev);
fprintf(vvp_out, " %%wait Ewait_%u;\n", cascade_counter);
cascade_counter += 1;
} else {
fprintf(vvp_out, " %%wait E_%p;\n", ev);
}
} else {
unsigned idx;
static unsigned int cascade_counter = 0;
ivl_event_t ev = ivl_stmt_events(net, 0);
fprintf(vvp_out, "Ewait_%u .event/or E_%p", cascade_counter, ev);
@ -1667,6 +1674,7 @@ static int show_stmt_wait(ivl_statement_t net, ivl_scope_t sscope)
ev = ivl_stmt_events(net, idx);
fprintf(vvp_out, ", E_%p", ev);
}
assert(ivl_stmt_needs_t0_trigger(net) == 0);
fprintf(vvp_out, ";\n %%wait Ewait_%u;\n", cascade_counter);
cascade_counter += 1;
}
@ -2358,6 +2366,9 @@ int draw_process(ivl_process_t net, void*x)
break;
case IVL_PR_ALWAYS:
case IVL_PR_ALWAYS_COMB:
case IVL_PR_ALWAYS_FF:
case IVL_PR_ALWAYS_LATCH:
fprintf(vvp_out, " %%jmp T_%u;\n", thread_count);
break;
}
@ -2368,6 +2379,9 @@ int draw_process(ivl_process_t net, void*x)
case IVL_PR_INITIAL:
case IVL_PR_ALWAYS:
case IVL_PR_ALWAYS_COMB:
case IVL_PR_ALWAYS_FF:
case IVL_PR_ALWAYS_LATCH:
if (init_flag) {
fprintf(vvp_out, " .thread T_%u, $init;\n", thread_count);
} else if (push_flag) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2016 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-2018 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
@ -860,6 +860,7 @@ static void draw_udp_in_scope(ivl_net_logic_t lptr)
* (.resolv, etc.) can be built before we build the .udp call.
* This matches what is done for the other primitives.
*/
assert(ivl_logic_pins(lptr) > 0);
ninp = ivl_logic_pins(lptr) - 1;
input_strings = calloc(ninp, sizeof(char*));
for (pdx = 0 ; pdx < ninp ; pdx += 1) {
@ -922,7 +923,7 @@ static void draw_logic_in_scope(ivl_net_logic_t lptr)
ivl_drive_t str1 = ivl_logic_drive1(lptr);
int level;
int ninp;
unsigned ninp;
const char **input_strings;
switch (ivl_logic_type(lptr)) {
@ -1055,8 +1056,8 @@ static void draw_logic_in_scope(ivl_net_logic_t lptr)
/* Get all the input label that I will use for parameters to
the functor that I create later. */
assert(ivl_logic_pins(lptr) > 0);
ninp = ivl_logic_pins(lptr) - 1;
assert(ninp >= 0);
input_strings = calloc(ninp, sizeof(char*));
for (pdx = 0 ; pdx < (unsigned)ninp ; pdx += 1)
input_strings[pdx] = draw_net_input(ivl_logic_pin(lptr, pdx+1));
@ -1521,6 +1522,16 @@ static void draw_lpm_cmp(ivl_lpm_t net)
type = "nee";
signed_string = "";
break;
case IVL_LPM_CMP_WEQ:
assert(dtc != IVL_VT_REAL); /* Should never get here! */
type = "weq";
signed_string = "";
break;
case IVL_LPM_CMP_WNE:
assert(dtc != IVL_VT_REAL); /* Should never get here! */
type = "wne";
signed_string = "";
break;
default:
assert(0);
}
@ -2143,6 +2154,8 @@ static void draw_lpm_in_scope(ivl_lpm_t net)
case IVL_LPM_CMP_GT:
case IVL_LPM_CMP_NE:
case IVL_LPM_CMP_NEE:
case IVL_LPM_CMP_WEQ:
case IVL_LPM_CMP_WNE:
draw_lpm_cmp(net);
return;
@ -2292,7 +2305,7 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent)
unsigned width = ivl_scope_mod_module_port_width(net,idx);
if( name == 0 )
name = "";
fprintf( vvp_out, " .port_info %u %s %u \"%s\"\n",
fprintf( vvp_out, " .port_info %u %s %u \"%s\";\n",
idx, vvp_port_info_type_str(ptype), width,
vvp_mangle_name(name) );
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2014 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-2018 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
@ -22,6 +22,7 @@
# include "verinum.h"
# include <iostream>
# include <cassert>
# include <climits>
# include <cmath> // Needed to get pow for as_double().
# include <cstdio> // Needed to get snprintf for as_string().
# include <algorithm>
@ -1444,7 +1445,8 @@ verinum operator / (const verinum&left, const verinum&right)
if (use_len <= (8*sizeof(long) - 1)) {
long l = left.as_long();
long r = right.as_long();
long v = l / r;
bool overflow = (l == LONG_MIN) && (r == -1);
long v = overflow ? LONG_MIN : l / r;
for (unsigned idx = 0 ; idx < use_len ; idx += 1) {
result.set(idx, (v & 1)? verinum::V1 : verinum::V0);
v >>= 1;
@ -1518,7 +1520,8 @@ verinum operator % (const verinum&left, const verinum&right)
/* Use native signed modulus to do the work. */
long l = left.as_long();
long r = right.as_long();
long v = l % r;
bool overflow = (l == LONG_MIN) && (r == -1);
long v = overflow ? 0 : l % r;
for (unsigned idx = 0 ; idx < use_len ; idx += 1) {
result.set(idx, (v & 1)? verinum::V1 : verinum::V0);
v >>= 1;

View File

@ -1,7 +1,7 @@
#ifndef VERIUSER_H
#define VERIUSER_H
/*
* Copyright (c) 2002-2014 Stephen Williams (steve@icarus.com)
* Copyright (c) 2002-2018 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
@ -159,6 +159,7 @@ extern void veriusertfs_register_table(p_tfcell vtable);
/* callback reasons */
#define reason_checktf 1
#define reason_sizetf 2
#define reason_calltf 3
#define reason_paramvc 7
#define reason_synch 8

View File

@ -1,7 +1,7 @@
#ifndef IVL_expression_H
#define IVL_expression_H
/*
* Copyright (c) 2011-2014 Stephen Williams (steve@icarus.com)
* Copyright (c) 2011-2018 Stephen Williams (steve@icarus.com)
* Copyright CERN 2015 / Stephen Williams (steve@icarus.com),
* Copyright CERN 2016
* @author Maciej Suminski (maciej.suminski@cern.ch)
@ -39,6 +39,10 @@ class VTypeArray;
class VTypePrimitive;
class ExpName;
#if __cplusplus < 201103L
#define unique_ptr auto_ptr
#endif
/*
* Helper class to recursively traverse an expression tree
* (i.e. complex expressions).
@ -273,8 +277,8 @@ class ExpAggregate : public Expression {
void dump(ostream&out, int indent) const;
private:
std::auto_ptr<Expression>expr_;
std::auto_ptr<ExpRange> range_;
std::unique_ptr<Expression>expr_;
std::unique_ptr<ExpRange> range_;
private: // not implemented
choice_t& operator= (const choice_t&);
};
@ -778,7 +782,7 @@ class ExpName : public Expression {
private:
Expression*index(unsigned int number) const;
std::auto_ptr<ExpName> prefix_;
std::unique_ptr<ExpName> prefix_;
perm_string name_;
std::list<Expression*>*indices_;
};
@ -1093,4 +1097,8 @@ private:
Expression*delay_;
};
#if __cplusplus < 201103L
#undef unique_ptr
#endif
#endif /* IVL_expression_H */

View File

@ -6,7 +6,7 @@
%{
/*
* Copyright (c) 2011 Stephen Williams (steve@icarus.com)
* Copyright (c) 2011-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
@ -748,7 +748,16 @@ yyscan_t prepare_lexor(FILE*fd)
return scanner;
}
/*
* Modern version of flex (>=2.5.9) can clean up the scanner data.
*/
void destroy_lexor(yyscan_t scanner)
{
# ifdef FLEX_SCANNER
# if YY_FLEX_MAJOR_VERSION >= 2 && YY_FLEX_MINOR_VERSION >= 5
# if YY_FLEX_MINOR_VERSION > 5 || defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9
yylex_destroy(scanner);
# endif
# endif
# endif
}

View File

@ -1,5 +1,5 @@
/*
* Copyright CERN 2016
* Copyright CERN 2016-2018
* @author Maciej Suminski (maciej.suminski@cern.ch)
*
* This source code is free software; you can redistribute it
@ -201,7 +201,7 @@ void preload_std_funcs(void)
args = new list<InterfacePort*>();
args->push_back(new InterfacePort(&primitive_REAL));
register_std_subprogram(new SubprogramBuiltin(perm_string::literal("integer"),
perm_string::literal("$signed"),
perm_string::literal("int'"),
args, &primitive_INTEGER));
/* function std_logic_vector

View File

@ -45,13 +45,14 @@ else
INCLUDE_PATH = -I. -I.. -I$(srcdir) -I$(srcdir)/..
endif
CPPFLAGS = $(INCLUDE_PATH) @file64_support@ @CPPFLAGS@ @DEFS@ @PICFLAG@
CPPFLAGS = $(INCLUDE_PATH) @file64_support@ @CPPFLAGS@ @DEFS@ -DICARUS_VPI_CONST=const @PICFLAG@
CFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CC@ @CFLAGS@
CXXFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CXX@ @CXXFLAGS@
LDFLAGS = @LDFLAGS@
# Object files for system.vpi
O = sys_table.o sys_convert.o sys_countdrivers.o sys_darray.o sys_deposit.o sys_display.o \
O = sys_table.o sys_convert.o sys_countdrivers.o sys_darray.o sys_deposit.o \
sys_display.o \
sys_fileio.o sys_finish.o sys_icarus.o sys_plusargs.o sys_queue.o \
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 \
@ -73,7 +74,8 @@ M = sys_clog2.o v2005_math.o
# Object files for va_math.vpi
V = va_math.o
V2009 = v2009_table.o v2009_array.o v2009_enum.o v2009_string.o
V2009 = v2009_table.o v2009_array.o v2009_bitvec.o v2009_enum.o v2009_string.o \
sys_priv.o
VHDL_SYS = vhdl_table.o sys_priv.o

View File

@ -45,83 +45,83 @@ variableScope:fstapi.c:6238
variableScope:fstapi.c:6466
// These functions are not used by Icarus
// fstReaderClrFacProcessMask()
unusedFunction:fstapi.c:3344
unusedFunction:fstapi.c:3345
// fstReaderClrFacProcessMaskAll()
unusedFunction:fstapi.c:3373
unusedFunction:fstapi.c:3374
// fstReaderGetAliasCount()
unusedFunction:fstapi.c:3436
unusedFunction:fstapi.c:3437
// fstReaderGetCurrentFlatScope()
unusedFunction:fstapi.c:3182
unusedFunction:fstapi.c:3183
// fstReaderGetAliasCount()
unusedFunction:fstapi.c:3279
unusedFunction:fstapi.c:3280
// fstReaderGetCurrentScopeUserInfo()
unusedFunction:fstapi.c:3196
unusedFunction:fstapi.c:3197
// fstReaderGetDateString()
unusedFunction:fstapi.c:3464
unusedFunction:fstapi.c:3465
// fstReaderGetDoubleEndianMatchState()
unusedFunction:fstapi.c:3450
unusedFunction:fstapi.c:3451
// fstReaderGetDumpActivityChangeTime()
unusedFunction:fstapi.c:3492
unusedFunction:fstapi.c:3493
// fstReaderGetDumpActivityChangeValue()
unusedFunction:fstapi.c:3507
unusedFunction:fstapi.c:3508
// fstReaderGetEndTime()
unusedFunction:fstapi.c:3401
unusedFunction:fstapi.c:3402
// fstReaderGetFacProcessMask()
unusedFunction:fstapi.c:3307
unusedFunction:fstapi.c:3308
// fstReaderGetFileType()
unusedFunction:fstapi.c:3471
unusedFunction:fstapi.c:3472
// fstReaderGetFseekFailed()
unusedFunction:fstapi.c:3292
unusedFunction:fstapi.c:3293
// fstReaderGetMaxHandle()
unusedFunction:fstapi.c:3429
unusedFunction:fstapi.c:3430
// fstReaderGetMemoryUsedByWriter()
unusedFunction:fstapi.c:3408
unusedFunction:fstapi.c:3409
// fstReaderGetNumberDumpActivityChanges()
unusedFunction:fstapi.c:3485
unusedFunction:fstapi.c:3486
// fstReaderGetScopeCount()
unusedFunction:fstapi.c:3415
unusedFunction:fstapi.c:3416
// fstReaderGetStartTime()
unusedFunction:fstapi.c:3394
unusedFunction:fstapi.c:3395
// fstReaderGetTimescale()
unusedFunction:fstapi.c:3387
unusedFunction:fstapi.c:3388
// fstReaderGetTimezero()
unusedFunction:fstapi.c:3478
unusedFunction:fstapi.c:3479
// fstReaderGetValueChangeSectionCount()
unusedFunction:fstapi.c:3443
unusedFunction:fstapi.c:3444
// fstReaderGetValueFromHandleAtTime()
unusedFunction:fstapi.c:5685
unusedFunction:fstapi.c:5686
// fstReaderGetVarCount()
unusedFunction:fstapi.c:3422
unusedFunction:fstapi.c:3423
// fstReaderGetVersionString()
unusedFunction:fstapi.c:3457
unusedFunction:fstapi.c:3458
// fstReaderIterBlocks()
unusedFunction:fstapi.c:4652
unusedFunction:fstapi.c:4653
// fstReaderIterBlocksSetNativeDoublesOnCallback()
unusedFunction:fstapi.c:3557
unusedFunction:fstapi.c:3558
// fstReaderIterateHier()
unusedFunction:fstapi.c:3782
unusedFunction:fstapi.c:3783
// fstReaderIterateHierRewind()
unusedFunction:fstapi.c:3762
unusedFunction:fstapi.c:3763
// fstReaderOpen()
unusedFunction:fstapi.c:4550
unusedFunction:fstapi.c:4551
// fstReaderOpenForUtilitiesOnly()
unusedFunction:fstapi.c:4542
unusedFunction:fstapi.c:4543
// fstReaderPushScope()
unusedFunction:fstapi.c:3244
unusedFunction:fstapi.c:3245
// fstReaderResetScope()
unusedFunction:fstapi.c:3233
unusedFunction:fstapi.c:3234
// fstReaderSetFacProcessMask()
unusedFunction:fstapi.c:3326
unusedFunction:fstapi.c:3327
// fstReaderSetFacProcessMaskAll()
unusedFunction:fstapi.c:3362
unusedFunction:fstapi.c:3363
// fstReaderSetLimitTimeRange()
unusedFunction:fstapi.c:3522
unusedFunction:fstapi.c:3523
// fstReaderSetUnlimitedTimeRange()
unusedFunction:fstapi.c:3535
unusedFunction:fstapi.c:3536
// fstReaderSetVcdExtensions()
unusedFunction:fstapi.c:3546
unusedFunction:fstapi.c:3547
// fstUtilityEscToBin()
unusedFunction:fstapi.c:6485
unusedFunction:fstapi.c:6544
// fstWriterCreateVar2()
unusedFunction:fstapi.c:2528
// fstWriterEmitVariableLengthValueChange()
@ -232,6 +232,10 @@ unusedLabel:fastlz.c:545
// These functions are not used by Icarus
// fastlz_compress_level()
unusedFunction:fastlz.c:150
// FASTLZ_COMPRESSOR()
unusedFunction:fastlz.c:162
// FASTLZ_DECOMPRESSOR()
unusedFunction:fastlz.c:416
// lz4.c from GTKWave
// These functions are not used by Icarus

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2009-2015 Tony Bybell.
* Copyright (c) 2009-2018 Tony Bybell.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@ -39,6 +39,7 @@ extern "C" {
#define FST_RDLOAD "FSTLOAD | "
typedef uint32_t fstHandle;
typedef uint32_t fstEnumHandle;
enum fstWriterPackType {
FST_WR_PT_ZLIB = 0,
@ -168,7 +169,11 @@ enum fstHierType {
FST_HT_ATTRBEGIN = 3,
FST_HT_ATTREND = 4,
FST_HT_MAX = 4
/* FST_HT_TREEBEGIN and FST_HT_TREEEND are not yet used by FST but are currently used when fstHier bridges other formats */
FST_HT_TREEBEGIN = 5,
FST_HT_TREEEND = 6,
FST_HT_MAX = 6
};
enum fstAttrType {
@ -192,9 +197,10 @@ enum fstMiscType {
FST_MT_SOURCESTEM = 4, /* use fstWriterSetSourceStem() to emit */
FST_MT_SOURCEISTEM = 5, /* use fstWriterSetSourceInstantiationStem() to emit */
FST_MT_VALUELIST = 6, /* use fstWriterSetValueList() to emit, followed by fstWriterCreateVar*() */
FST_MT_UNKNOWN = 7,
FST_MT_ENUMTABLE = 7, /* use fstWriterCreateEnumTable() and fstWriterEmitEnumTableRef() to emit */
FST_MT_UNKNOWN = 8,
FST_MT_MAX = 7
FST_MT_MAX = 8
};
enum fstArrayType {
@ -224,7 +230,10 @@ enum fstEnumValueType {
FST_EV_SV_UNSIGNED_LONGINT = 12,
FST_EV_SV_UNSIGNED_BYTE = 13,
FST_EV_MAX = 13
FST_EV_REG = 14,
FST_EV_TIME = 15,
FST_EV_MAX = 15
};
enum fstPackType {
@ -320,11 +329,21 @@ union {
};
struct fstETab
{
char *name;
uint32_t elem_count;
char **literal_arr;
char **val_arr;
};
/*
* writer functions
*/
void fstWriterClose(void *ctx);
void * fstWriterCreate(const char *nam, int use_compressed_hier);
fstEnumHandle fstWriterCreateEnumTable(void *ctx, const char *name, uint32_t elem_count, unsigned int min_valbits, const char **literal_arr, const char **val_arr);
/* used for Verilog/SV */
fstHandle fstWriterCreateVar(void *ctx, enum fstVarType vt, enum fstVarDir vd,
uint32_t len, const char *nam, fstHandle aliasHandle);
@ -333,9 +352,10 @@ fstHandle fstWriterCreateVar(void *ctx, enum fstVarType vt, enum fstVarDir
fstHandle fstWriterCreateVar2(void *ctx, enum fstVarType vt, enum fstVarDir vd,
uint32_t len, const char *nam, fstHandle aliasHandle,
const char *type, enum fstSupplementalVarType svt, enum fstSupplementalDataType sdt);
void fstWriterEmitDumpActive(void *ctx, int enable);
void fstWriterEmitEnumTableRef(void *ctx, fstEnumHandle handle);
void fstWriterEmitValueChange(void *ctx, fstHandle handle, const void *val);
void fstWriterEmitVariableLengthValueChange(void *ctx, fstHandle handle, const void *val, uint32_t len);
void fstWriterEmitDumpActive(void *ctx, int enable);
void fstWriterEmitTimeChange(void *ctx, uint64_t tim);
void fstWriterFlushContext(void *ctx);
int fstWriterGetDumpSizeLimitReached(void *ctx);
@ -418,8 +438,12 @@ void fstReaderSetVcdExtensions(void *ctx, int enable);
/*
* utility functions
*/
int fstUtilityBinToEsc(unsigned char *d, unsigned char *s, int len);
int fstUtilityBinToEscConvertedLen(const unsigned char *s, int len); /* used for mallocs for fstUtilityBinToEsc() */
int fstUtilityBinToEsc(unsigned char *d, const unsigned char *s, int len);
int fstUtilityEscToBin(unsigned char *d, unsigned char *s, int len);
struct fstETab *fstUtilityExtractEnumTableFromString(const char *s);
void fstUtilityFreeEnumTable(struct fstETab *etab); /* must use to free fstETab properly */
#ifdef __cplusplus
}

View File

@ -97,7 +97,7 @@ if (lo<hi)
static void wave_msort(struct lxt2_wr_symbol **a, int num)
{
struct lxt2_wr_symbol **b = malloc(((num/2)+1) * sizeof(struct lxt2_wr_symbol *));
struct lxt2_wr_symbol **b = (struct lxt2_wr_symbol**)malloc(((num/2)+1) * sizeof(struct lxt2_wr_symbol *));
wave_mergesort(a, b, 0, num-1);
@ -583,7 +583,7 @@ unsigned int i;
if((lt)&&(lt->numfacs))
{
struct lxt2_wr_symbol *s = lt->symchain;
struct lxt2_wr_symbol **aliascache = calloc(lt->numalias ? lt->numalias : 1, sizeof(struct lxt2_wr_symbol *));
struct lxt2_wr_symbol **aliascache = (struct lxt2_wr_symbol**)calloc(lt->numalias ? lt->numalias : 1, sizeof(struct lxt2_wr_symbol *));
unsigned int aliases_encountered, facs_encountered;
lt->sorted_facs = (struct lxt2_wr_symbol **)calloc(lt->numfacs, sizeof(struct lxt2_wr_symbol *));
@ -920,7 +920,7 @@ if(flags&LXT2_WR_SYM_F_DOUBLE)
s->len = 32;
}
s->value = malloc(s->len + 1);
s->value = (char*)malloc(s->len + 1);
memset(s->value, lt->initial_value, s->len);
s->value[s->len]=0;
@ -1017,7 +1017,7 @@ static void lxt2_wr_emit_do_breakfile(struct lxt2_wr_trace *lt)
{
unsigned int len = strlen(lt->lxtname);
int i;
char *tname = malloc(len + 30);
char *tname = (char*)malloc(len + 30);
FILE *f2, *clone;
off_t cnt, seg;
char buf[32768];
@ -1810,13 +1810,13 @@ while(s->aliased_to) /* find root alias if exists */
valuelen = strlen(value); /* ensure string is proper length */
if(valuelen == s->len)
{
vfix = wave_alloca(s->len+1);
vfix = (char*)wave_alloca(s->len+1);
strcpy(vfix, value);
value = vfix;
}
else
{
vfix = wave_alloca(s->len+1);
vfix = (char*)wave_alloca(s->len+1);
if(valuelen < s->len)
{
@ -2088,7 +2088,7 @@ if((lt)&&(lt->blackout))
else
{
free(s->value);
s->value = calloc(1, 1*sizeof(char));
s->value = (char*)calloc(1, 1*sizeof(char));
}
}
}
@ -2101,9 +2101,11 @@ if((lt)&&(lt->blackout))
{
if((!(s->flags&LXT2_WR_SYM_F_ALIAS))&&(s->rows<2))
{
char tmp[16]; /* To get rid of the warning */
if(!(s->flags&(LXT2_WR_SYM_F_DOUBLE|LXT2_WR_SYM_F_STRING)))
{
lxt2_wr_emit_value_bit_string(lt, s, 0, "x");
strcpy(tmp, "x");
lxt2_wr_emit_value_bit_string(lt, s, 0, tmp);
}
else if (s->flags&LXT2_WR_SYM_F_DOUBLE)
{
@ -2113,7 +2115,8 @@ if((lt)&&(lt->blackout))
}
else if (s->flags&LXT2_WR_SYM_F_STRING)
{
lxt2_wr_emit_value_string(lt, s, 0, "UNDEF");
strcpy(tmp, "UNDEF");
lxt2_wr_emit_value_string(lt, s, 0, tmp);
}
}
s=s->symchain;
@ -2202,4 +2205,3 @@ if(lt)
lt->timezero = timeval;
}
}

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