Merge branch 'master' of github.com:steveicarus/iverilog

This commit is contained in:
Stephen Williams 2018-04-11 13:40:04 -07:00
commit 6c39348d1a
112 changed files with 3684 additions and 1973 deletions

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

@ -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

@ -77,10 +77,16 @@ the configure scripts.
Unpack the tar-ball and cd into the verilog-######### directory
(presumably that is how you got to this README) and compile the source
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
@ -120,6 +120,10 @@ 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
@ -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 [-EiSvV] [-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,9 @@ 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;
@ -344,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)
@ -410,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);
@ -421,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);
@ -450,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);
@ -501,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");
@ -517,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");
@ -561,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) {
@ -990,7 +1028,7 @@ int main(int argc, char **argv)
}
}
while ((opt = getopt(argc, argv, "B:c:D:d:Ef:g:hl:I:iM: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':
@ -1046,8 +1084,8 @@ int main(int argc, char **argv)
break;
case 'i':
ignore_missing_modules = 1;
break;
ignore_missing_modules = 1;
break;
case 'l':
process_file_name(optarg, 1);
@ -1093,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;
@ -1135,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);
}
@ -1288,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-2017 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;
}
@ -2264,8 +2278,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;
}
@ -3141,6 +3155,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 +3481,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 +5371,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 +5623,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: "

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)
@ -1758,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);

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
@ -2355,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
@ -2918,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;
@ -4202,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);
@ -4212,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;
@ -4478,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);
@ -4498,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 */);
@ -5368,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());
@ -5415,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. */
@ -5695,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;
}
@ -6127,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) {
@ -6142,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"
@ -6150,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,
@ -6159,37 +6187,158 @@ 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)
/*
* Check to see if the always_* processes only contain synthesizable
* constructs.
*/
bool Design::check_proc_synth() const
{
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;
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());
}
}
return result;
}
cur->second->elaborate(this, cur->first);
/*
* 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;
}
}
/*
@ -6211,8 +6360,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;
@ -6220,23 +6374,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);
@ -6267,9 +6434,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
@ -6339,6 +6510,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;
@ -6367,8 +6542,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;
@ -6430,8 +6603,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;
@ -6446,10 +6617,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: "
@ -6457,5 +6629,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-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
@ -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;

View File

@ -1,5 +1,5 @@
/*
* 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
@ -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));
@ -1347,6 +1358,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

@ -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

@ -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;
}

84
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;
@ -179,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.
*/
@ -777,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)
@ -863,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;
@ -921,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"
@ -936,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) {
@ -1035,8 +1085,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);
@ -1050,22 +1102,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 ) {
@ -1183,12 +1229,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);

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) 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

@ -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);
@ -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;
}

211
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;
@ -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_;
@ -4624,7 +4678,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 +4710,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 +4765,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 +4841,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 +4889,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 +4911,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 +4967,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 +4979,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 +4992,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 +5007,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 +5021,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 */

179
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
@ -683,7 +678,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 '+' '-'
@ -692,7 +687,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
@ -700,12 +695,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
@ -1137,11 +1142,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. */
@ -1726,17 +1727,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;
}
@ -2044,7 +2046,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
@ -2128,10 +2133,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
@ -2143,7 +2154,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
@ -2190,8 +2200,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();
@ -2217,30 +2234,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 */
@ -3275,6 +3296,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);
@ -3295,6 +3321,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);
@ -4406,47 +4437,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. */
@ -4459,11 +4449,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;
@ -4500,8 +4487,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
@ -4879,6 +4864,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);
@ -4893,6 +4890,8 @@ module_item
| attribute_list_opt assertion_item
| timeunits_declaration
| class_declaration
| task_declaration
@ -5016,14 +5015,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
@ -6434,7 +6425,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

552
pform.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)
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
@ -63,20 +63,19 @@ map<perm_string,Module*> pform_modules;
map<perm_string,PUdp*> pform_primitives;
/*
* typedefs in the $root scope go here.
* The pform_units is a list of the SystemVerilog compilation unit scopes.
* The current compilation unit is the last element in the list. All items
* declared or defined at the top level (outside any design element) are
* added to the current compilation unit scope.
*/
map<perm_string,data_type_t*>pform_typedefs;
set<enum_type_t*>pform_enum_sets;
vector<PPackage*> pform_units;
/*
* Class definitions in the $root scope go here.
*/
map<perm_string,PClass*> pform_classes;
/*
* Task and function definitions in the $root scope go here.
*/
map<perm_string,PTaskFunc*> pform_tasks;
static bool is_compilation_unit(LexicalScope*scope)
{
// A compilation unit is the only scope that doesn't have a parent.
assert(scope);
return scope->parent_scope() == 0;
}
std::string vlltype::get_fileline() const
{
@ -357,30 +356,27 @@ static PModport*pform_cur_modport = 0;
static NetNet::Type pform_default_nettype = NetNet::WIRE;
/*
* These variables track the current time scale, as well as where the
* timescale was set. This supports warnings about tangled timescales.
* These variables track the time scale set by the most recent `timescale
* directive. Time scales set by SystemVerilog timeunit and timeprecision
* declarations are stored directly in the current lexical scope.
*/
static int pform_time_unit;
static int pform_time_prec;
/* These two flags check the initial timeprecision and timeunit
* declaration inside a module.
*/
static bool tp_decl_flag = false;
static bool tu_decl_flag = false;
/*
* Flags used to set time_from_timescale based on timeunit and
* timeprecision.
* These variables track where the most recent `timescale directive
* occurred. This allows us to warn about time scales that are inherited
* from another file.
*/
static bool tu_global_flag = false;
static bool tp_global_flag = false;
static bool tu_local_flag = false;
static bool tp_local_flag = false;
static char*pform_timescale_file = 0;
static unsigned pform_timescale_line;
/*
* These variables track whether we can accept new timeunits declarations.
*/
bool allow_timeunit_decl = true;
bool allow_timeprec_decl = true;
static inline void FILE_NAME(LineInfo*obj, const char*file, unsigned lineno)
{
obj->set_lineno(lineno);
@ -406,6 +402,7 @@ void pform_pop_scope()
{
assert(lexical_scope);
lexical_scope = lexical_scope->parent_scope();
assert(lexical_scope);
}
static LexicalScope::lifetime_t find_lifetime(LexicalScope::lifetime_t lifetime)
@ -413,10 +410,7 @@ static LexicalScope::lifetime_t find_lifetime(LexicalScope::lifetime_t lifetime)
if (lifetime != LexicalScope::INHERITED)
return lifetime;
if (lexical_scope != 0)
return lexical_scope->default_lifetime;
return LexicalScope::STATIC;
return lexical_scope->default_lifetime;
}
static PScopeExtra* find_nearest_scopex(LexicalScope*scope)
@ -430,17 +424,59 @@ static PScopeExtra* find_nearest_scopex(LexicalScope*scope)
}
/*
* Set the local time unit/precision to the global value.
* Set the local time unit/precision. This version is used for setting
* the time scale for design elements (modules, packages, etc.) and is
* called after any initial timeunit and timeprecision declarations
* have been parsed.
*/
static void pform_set_scope_timescale(PScope*scope, const struct vlltype&loc)
void pform_set_scope_timescale(const struct vlltype&loc)
{
scope->time_unit = pform_time_unit;
scope->time_precision = pform_time_prec;
/* If we have a timescale file then the time information is from
* a timescale directive. */
scope->time_from_timescale = pform_timescale_file != 0;
PScopeExtra*scope = dynamic_cast<PScopeExtra*>(lexical_scope);
assert(scope);
if (warn_timescale && (lexical_scope == 0) && pform_timescale_file
PScopeExtra*parent = find_nearest_scopex(scope->parent_scope());
bool used_global_timescale = false;
if (scope->time_unit_is_default) {
if (is_compilation_unit(scope)) {
scope->time_unit = def_ts_units;
} else if (!is_compilation_unit(parent)) {
scope->time_unit = parent->time_unit;
scope->time_unit_is_default = parent->time_unit_is_default;
} else if (pform_timescale_file != 0) {
scope->time_unit = pform_time_unit;
scope->time_unit_is_default = false;
used_global_timescale = true;
} else /* parent is compilation unit */ {
scope->time_unit = parent->time_unit;
scope->time_unit_is_default = parent->time_unit_is_default;
}
}
if (scope->time_prec_is_default) {
if (is_compilation_unit(scope)) {
scope->time_precision = def_ts_prec;
} else if (!is_compilation_unit(parent)) {
scope->time_precision = parent->time_precision;
scope->time_prec_is_default = parent->time_prec_is_default;
} else if (pform_timescale_file != 0) {
scope->time_precision = pform_time_prec;
scope->time_prec_is_default = false;
used_global_timescale = true;
} else {
scope->time_precision = parent->time_precision;
scope->time_prec_is_default = parent->time_prec_is_default;
}
}
if (gn_system_verilog() && (scope->time_unit < scope->time_precision)) {
if (scope->time_unit_is_local || scope->time_prec_is_local) {
VLerror("error: a timeprecision is missing or is too large!");
}
} else {
assert(scope->time_unit >= scope->time_precision);
}
if (warn_timescale && used_global_timescale
&& (strcmp(pform_timescale_file, loc.text) != 0)) {
cerr << loc.get_fileline() << ": warning: "
@ -449,6 +485,22 @@ static void pform_set_scope_timescale(PScope*scope, const struct vlltype&loc)
cerr << pform_timescale_file << ":" << pform_timescale_line
<< ": ...: The inherited timescale is here." << endl;
}
allow_timeunit_decl = false;
allow_timeprec_decl = false;
}
/*
* Set the local time unit/precision. This version is used for setting
* the time scale for subsidiary items (classes, subroutines, etc.),
* which simply inherit their time scale from their parent scope.
*/
static void pform_set_scope_timescale(PScope*scope, const PScope*parent)
{
scope->time_unit = parent->time_unit;
scope->time_precision = parent->time_precision;
scope->time_unit_is_default = parent->time_unit_is_default;
scope->time_prec_is_default = parent->time_prec_is_default;
}
PClass* pform_push_class_scope(const struct vlltype&loc, perm_string name,
@ -458,19 +510,11 @@ PClass* pform_push_class_scope(const struct vlltype&loc, perm_string name,
class_scope->default_lifetime = find_lifetime(lifetime);
FILE_NAME(class_scope, loc);
pform_set_scope_timescale(class_scope, loc);
PScopeExtra*scopex = find_nearest_scopex(lexical_scope);
assert(scopex);
assert(!pform_cur_generate);
/* If no scope was found then this is being defined in the
* compilation unit scope. */
if (scopex == 0) {
pform_classes[name] = class_scope;
lexical_scope = class_scope;
return class_scope;
}
pform_set_scope_timescale(class_scope, scopex);
if (scopex->classes.find(name) != scopex->classes.end()) {
cerr << class_scope->get_fileline() << ": error: duplicate "
@ -492,7 +536,8 @@ PPackage* pform_push_package_scope(const struct vlltype&loc, perm_string name,
pkg_scope->default_lifetime = find_lifetime(lifetime);
FILE_NAME(pkg_scope, loc);
pform_set_scope_timescale(pkg_scope, loc);
allow_timeunit_decl = true;
allow_timeprec_decl = true;
lexical_scope = pkg_scope;
return pkg_scope;
@ -510,15 +555,16 @@ PTask* pform_push_task_scope(const struct vlltype&loc, char*name,
task->default_lifetime = default_lifetime;
FILE_NAME(task, loc);
pform_set_scope_timescale(task, loc);
PScopeExtra*scopex = find_nearest_scopex(lexical_scope);
if ((scopex == 0) && !gn_system_verilog()) {
assert(scopex);
if (is_compilation_unit(scopex) && !gn_system_verilog()) {
cerr << task->get_fileline() << ": error: task declarations "
"must be contained within a module." << endl;
error_count += 1;
}
pform_set_scope_timescale(task, scopex);
if (pform_cur_generate) {
// Check if the task is already in the dictionary.
if (pform_cur_generate->tasks.find(task->pscope_name()) !=
@ -530,7 +576,7 @@ PTask* pform_push_task_scope(const struct vlltype&loc, char*name,
error_count += 1;
}
pform_cur_generate->tasks[task->pscope_name()] = task;
} else if (scopex) {
} else {
// Check if the task is already in the dictionary.
if (scopex->tasks.find(task->pscope_name()) != scopex->tasks.end()) {
cerr << task->get_fileline() << ": error: duplicate "
@ -539,15 +585,6 @@ PTask* pform_push_task_scope(const struct vlltype&loc, char*name,
error_count += 1;
}
scopex->tasks[task->pscope_name()] = task;
} else {
if (pform_tasks.find(task_name) != pform_tasks.end()) {
cerr << task->get_fileline() << ": error: "
<< "Duplicate definition for task '" << name
<< "' in $root scope." << endl;
error_count += 1;
}
pform_tasks[task_name] = task;
}
lexical_scope = task;
@ -567,15 +604,16 @@ PFunction* pform_push_function_scope(const struct vlltype&loc, const char*name,
func->default_lifetime = default_lifetime;
FILE_NAME(func, loc);
pform_set_scope_timescale(func, loc);
PScopeExtra*scopex = find_nearest_scopex(lexical_scope);
if ((scopex == 0) && !gn_system_verilog()) {
assert(scopex);
if (is_compilation_unit(scopex) && !gn_system_verilog()) {
cerr << func->get_fileline() << ": error: function declarations "
"must be contained within a module." << endl;
error_count += 1;
}
pform_set_scope_timescale(func, scopex);
if (pform_cur_generate) {
// Check if the function is already in the dictionary.
if (pform_cur_generate->funcs.find(func->pscope_name()) !=
@ -588,7 +626,7 @@ PFunction* pform_push_function_scope(const struct vlltype&loc, const char*name,
}
pform_cur_generate->funcs[func->pscope_name()] = func;
} else if (scopex != 0) {
} else {
// Check if the function is already in the dictionary.
if (scopex->funcs.find(func->pscope_name()) != scopex->funcs.end()) {
cerr << func->get_fileline() << ": error: duplicate "
@ -597,15 +635,6 @@ PFunction* pform_push_function_scope(const struct vlltype&loc, const char*name,
error_count += 1;
}
scopex->funcs[func->pscope_name()] = func;
} else {
if (pform_tasks.find(func_name) != pform_tasks.end()) {
cerr << func->get_fileline() << ": error: "
<< "Duplicate definition for function '" << name
<< "' in $root scope." << endl;
error_count += 1;
}
pform_tasks[func_name] = func;
}
lexical_scope = func;
@ -705,23 +734,31 @@ static void pform_put_wire_in_scope(perm_string name, PWire*net)
static void pform_put_enum_type_in_scope(enum_type_t*enum_set)
{
if (lexical_scope) {
lexical_scope->enum_sets.insert(enum_set);
} else {
pform_enum_sets.insert(enum_set);
}
lexical_scope->enum_sets.insert(enum_set);
}
PWire*pform_get_make_wire_in_scope(perm_string name, NetNet::Type net_type, NetNet::PortType port_type, ivl_variable_type_t vt_type)
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)
{
PWire*cur = pform_get_wire_in_scope(name);
// If the wire already exists and is fully defined, this
// must be a redeclaration. Start again with a new wire.
if (cur && cur->get_data_type() != IVL_VT_NO_TYPE) {
LineInfo tloc;
FILE_NAME(&tloc, li);
cerr << tloc.get_fileline() << ": error: duplicate declaration "
"for net or variable '" << name << "'." << endl;
error_count += 1;
delete cur;
cur = 0;
}
if (cur == 0) {
cur = new PWire(name, net_type, port_type, vt_type);
pform_put_wire_in_scope(name, cur);
} else {
// If this is a duplicate wire, the data type has already
// been set, then return NULL.
if (cur->get_data_type() != IVL_VT_NO_TYPE) return 0;
bool rc = cur->set_wire_type(net_type);
assert(rc);
rc = cur->set_data_type(vt_type);
@ -736,12 +773,7 @@ void pform_set_typedef(perm_string name, data_type_t*data_type, std::list<pform_
if(unp_ranges)
data_type = new uarray_type_t(data_type, unp_ranges);
// If we are in a lexical scope (i.e. a package or module)
// then put the typedef into that scope. Otherwise, put it
// into the $root scope.
data_type_t*&ref = lexical_scope
? lexical_scope->typedefs[name]
: pform_typedefs[name];
data_type_t*&ref = lexical_scope->typedefs[name];
ivl_assert(*data_type, ref == 0);
ref = data_type;
@ -751,25 +783,10 @@ void pform_set_typedef(perm_string name, data_type_t*data_type, std::list<pform_
}
}
static data_type_t* test_type_identifier_in_root(perm_string name)
{
map<perm_string,data_type_t*>::iterator cur = pform_typedefs.find(name);
if (cur != pform_typedefs.end())
return cur->second;
else
return 0;
}
data_type_t* pform_test_type_identifier(const char*txt)
{
perm_string name = lex_strings.make(txt);
// If there is no lexical_scope yet, then look only in the
// $root scope for typedefs.
if (lexical_scope == 0) {
return test_type_identifier_in_root(name);
}
LexicalScope*cur_scope = lexical_scope;
do {
map<perm_string,data_type_t*>::iterator cur;
@ -799,10 +816,6 @@ data_type_t* pform_test_type_identifier(const char*txt)
cur_scope = cur_scope->parent_scope();
} while (cur_scope);
// See if there is a typedef in the $root scope.
if (data_type_t*tmp = test_type_identifier_in_root(name))
return tmp;
return 0;
}
@ -813,13 +826,6 @@ data_type_t* pform_test_type_identifier(const char*txt)
*/
bool pform_test_type_identifier_local(perm_string name)
{
if (lexical_scope == 0) {
if (test_type_identifier_in_root(name))
return true;
else
return false;
}
LexicalScope*cur_scope = lexical_scope;
map<perm_string,data_type_t*>::iterator cur;
@ -970,64 +976,23 @@ static void pform_declare_implicit_nets(PExpr*expr)
/*
* The lexor calls this function to set the active timescale when it
* detects a `timescale directive. The function saves the directive
* values (for use by modules) and if warnings are enabled checks to
* see if some modules have no timescale.
* values (for use by subsequent design elements) and if warnings are
* enabled checks to see if some design elements have no timescale.
*/
void pform_set_timescale(int unit, int prec,
const char*file, unsigned lineno)
{
bool first_flag = true;
assert(unit >= prec);
pform_time_unit = unit;
pform_time_prec = prec;
/* A `timescale clears the timeunit/timeprecision state. */
tu_global_flag = false;
tp_global_flag = false;
if (pform_timescale_file) {
free(pform_timescale_file);
first_flag = false;
}
if (file) pform_timescale_file = strdup(file);
else pform_timescale_file = 0;
pform_timescale_line = lineno;
if (!warn_timescale || !first_flag || !file) return;
/* Look to see if we have any modules without a timescale. */
bool have_no_ts = false;
map<perm_string,Module*>::iterator mod;
for (mod = pform_modules.begin(); mod != pform_modules.end(); ++ mod ) {
const Module*mp = (*mod).second;
if (mp->time_from_timescale ||
mp->timescale_warn_done) continue;
have_no_ts = true;
break;
}
/* If we do then print a message for the new ones. */
if (have_no_ts) {
cerr << file << ":" << lineno << ": warning: "
<< "Some modules have no timescale. This may cause"
<< endl;
cerr << file << ":" << lineno << ": : "
<< "confusing timing results. Affected modules are:"
<< endl;
for (mod = pform_modules.begin()
; mod != pform_modules.end() ; ++ mod ) {
Module*mp = (*mod).second;
if (mp->time_from_timescale ||
mp->timescale_warn_done) continue;
mp->timescale_warn_done = true;
cerr << file << ":" << lineno << ": : "
<< " -- module " << (*mod).first
<< " declared here: " << mp->get_fileline() << endl;
}
}
}
bool get_time_unit(const char*cp, int &unit)
@ -1147,70 +1112,56 @@ static bool get_time_unit_prec(const char*cp, int &res, bool is_unit)
return true;
}
void pform_set_timeunit(const char*txt, bool in_module, bool only_check)
void pform_set_timeunit(const char*txt, bool initial_decl)
{
int val;
if (get_time_unit_prec(txt, val, true)) return;
if (in_module) {
if (!only_check) {
pform_cur_module.front()->time_unit = val;
tu_decl_flag = true;
tu_local_flag = true;
} else if (!tu_decl_flag) {
VLerror(yylloc, "error: repeat timeunit found and the "
"initial module timeunit is missing.");
return;
} else if (pform_cur_module.front()->time_unit != val) {
VLerror(yylloc, "error: repeat timeunit does not match "
"the initial module timeunit "
"declaration.");
return;
}
PScopeExtra*scope = dynamic_cast<PScopeExtra*>(lexical_scope);
assert(scope);
} else {
/* Skip a global timeunit when `timescale is defined. */
if (pform_timescale_file) return;
tu_global_flag = true;
pform_time_unit = val;
if (initial_decl) {
scope->time_unit = val;
scope->time_unit_is_local = true;
scope->time_unit_is_default = false;
allow_timeunit_decl = false;
} else if (!scope->time_unit_is_local) {
VLerror(yylloc, "error: repeat timeunit found and the initial "
"timeunit for this scope is missing.");
} else if (scope->time_unit != val) {
VLerror(yylloc, "error: repeat timeunit does not match the "
"initial timeunit for this scope.");
}
}
int pform_get_timeunit()
{
if (pform_cur_module.empty())
return pform_time_unit;
else
return pform_cur_module.front()->time_unit;
PScopeExtra*scopex = find_nearest_scopex(lexical_scope);
assert(scopex);
return scopex->time_unit;
}
void pform_set_timeprecision(const char*txt, bool in_module, bool only_check)
void pform_set_timeprec(const char*txt, bool initial_decl)
{
int val;
if (get_time_unit_prec(txt, val, false)) return;
if (in_module) {
if (!only_check) {
pform_cur_module.front()->time_precision = val;
tp_decl_flag = true;
tp_local_flag = true;
} else if (!tp_decl_flag) {
VLerror(yylloc, "error: repeat timeprecision found and the "
"initial module timeprecision is missing.");
return;
} else if (pform_cur_module.front()->time_precision != val) {
VLerror(yylloc, "error: repeat timeprecision does not match "
"the initial module timeprecision "
"declaration.");
return;
}
} else {
/* Skip a global timeprecision when `timescale is defined. */
if (pform_timescale_file) return;
pform_time_prec = val;
tp_global_flag=true;
PScopeExtra*scope = dynamic_cast<PScopeExtra*>(lexical_scope);
assert(scope);
if (initial_decl) {
scope->time_precision = val;
scope->time_prec_is_local = true;
scope->time_prec_is_default = false;
allow_timeprec_decl = false;
} else if (!scope->time_prec_is_local) {
VLerror(yylloc, "error: repeat timeprecision found and the initial "
"timeprecision for this scope is missing.");
} else if (scope->time_precision != val) {
VLerror(yylloc, "error: repeat timeprecision does not match the "
"initial timeprecision for this scope.");
}
}
@ -1315,14 +1266,13 @@ void pform_startmodule(const struct vlltype&loc, const char*name,
FILE_NAME(cur_module, loc);
pform_set_scope_timescale(cur_module, loc);
tu_local_flag = tu_global_flag;
tp_local_flag = tp_global_flag;
cur_module->library_flag = pform_library_flag;
pform_cur_module.push_front(cur_module);
allow_timeunit_decl = true;
allow_timeprec_decl = true;
lexical_scope = cur_module;
/* The generate scheme numbering starts with *1*, not
@ -1332,21 +1282,6 @@ void pform_startmodule(const struct vlltype&loc, const char*name,
pform_bind_attributes(cur_module->attributes, attr);
}
/*
* In SystemVerilog we can have separate timeunit and timeprecision
* declarations. We need to have the values worked out by time this
* task is called.
*/
void pform_check_timeunit_prec()
{
assert(! pform_cur_module.empty());
if (gn_system_verilog() &&
(pform_cur_module.front()->time_unit < pform_cur_module.front()->time_precision)) {
VLerror("error: a timeprecision is missing or is too large!");
} else assert(pform_cur_module.front()->time_unit >=
pform_cur_module.front()->time_precision);
}
/*
* This function is called by the parser to make a simple port
* reference. This is a name without a .X(...), so the internal name
@ -1390,8 +1325,6 @@ void pform_endmodule(const char*name, bool inside_celldefine,
Module*cur_module = pform_cur_module.front();
pform_cur_module.pop_front();
cur_module->time_from_timescale = (tu_local_flag && tp_local_flag)
|| (pform_timescale_file != 0);
perm_string mod_name = cur_module->mod_name();
assert(strcmp(name, mod_name) == 0);
cur_module->is_cell = inside_celldefine;
@ -1418,16 +1351,9 @@ void pform_endmodule(const char*name, bool inside_celldefine,
use_module_map[mod_name] = cur_module;
}
// The current lexical scope should be this module by now, and
// this module should not have a parent lexical scope.
// The current lexical scope should be this module by now.
ivl_assert(*cur_module, lexical_scope == cur_module);
pform_pop_scope();
ivl_assert(*cur_module, ! pform_cur_module.empty() || lexical_scope == 0);
tp_decl_flag = false;
tu_decl_flag = false;
tu_local_flag = false;
tp_local_flag = false;
}
static void pform_add_genvar(const struct vlltype&li, const perm_string&name,
@ -2768,19 +2694,16 @@ void pform_makewire(const vlltype&li,
* net_decl_assign_t argument.
*/
void pform_makewire(const struct vlltype&li,
std::list<PExpr*>*, str_pair_t ,
std::list<PExpr*>*delay,
str_pair_t str,
std::list<decl_assignment_t*>*assign_list,
NetNet::Type type,
data_type_t*data_type)
{
if ((lexical_scope == 0) && !gn_system_verilog()) {
if (is_compilation_unit(lexical_scope) && !gn_system_verilog()) {
VLerror(li, "error: variable declarations must be contained within a module.");
return;
}
if (lexical_scope == 0) {
VLerror(li, "sorry: variable declarations in the $root scope are not yet supported.");
return;
}
list<perm_string>*names = new list<perm_string>;
@ -2795,8 +2718,18 @@ void pform_makewire(const struct vlltype&li,
while (! assign_list->empty()) {
decl_assignment_t*first = assign_list->front();
assign_list->pop_front();
// For now, do not handle assignment expressions.
assert(! first->expr.get());
if (PExpr*expr = first->expr.release()) {
if (type == NetNet::REG || type == NetNet::IMPLICIT_REG) {
pform_make_var_init(li, first->name, expr);
} else {
PWire*cur = pform_get_wire_in_scope(first->name);
assert(cur);
PEIdent*lval = new PEIdent(first->name);
FILE_NAME(lval, li.text, li.first_line);
PGAssign*ass = pform_make_pgassign(lval, expr, delay, str);
FILE_NAME(ass, li.text, li.first_line);
}
}
delete first;
}
}
@ -3080,18 +3013,16 @@ void pform_set_parameter(const struct vlltype&loc,
LexicalScope::range_t*value_range)
{
LexicalScope*scope = lexical_scope;
if ((scope == 0) && !gn_system_verilog()) {
if (is_compilation_unit(scope) && !gn_system_verilog()) {
VLerror(loc, "error: parameter declarations must be contained within a module.");
return;
}
if (scope == 0) {
VLerror(loc, "sorry: parameter declarations in the $root scope are not yet supported.");
return;
}
if (scope == pform_cur_generate) {
VLerror("parameter declarations are not permitted in generate blocks");
return;
}
PScopeExtra*scopex = find_nearest_scopex(lexical_scope);
assert(scopex);
// Check if the parameter name is already in the dictionary.
if (scope->parameters.find(name) != scope->parameters.end()) {
@ -3099,14 +3030,14 @@ void pform_set_parameter(const struct vlltype&loc,
FILE_NAME(&tloc, loc);
cerr << tloc.get_fileline() << ": error: duplicate definition "
"for parameter '" << name << "' in '"
<< pform_cur_module.front()->mod_name() << "'." << endl;
<< scopex->pscope_name() << "'." << endl;
error_count += 1;
}
if (scope->localparams.find(name) != scope->localparams.end()) {
LineInfo tloc;
FILE_NAME(&tloc, loc);
cerr << tloc.get_fileline() << ": error: localparam and "
<< "parameter in '" << pform_cur_module.front()->mod_name()
<< "parameter in '" << scopex->pscope_name()
<< "' have the same name '" << name << "'." << endl;
error_count += 1;
}
@ -3118,7 +3049,7 @@ void pform_set_parameter(const struct vlltype&loc,
LineInfo tloc;
FILE_NAME(&tloc, loc);
cerr << tloc.get_fileline() << ": error: specparam and "
"parameter in '" << pform_cur_module.front()->mod_name()
"parameter in '" << scopex->pscope_name()
<< "' have the same name '" << name << "'." << endl;
error_count += 1;
}
@ -3155,14 +3086,12 @@ void pform_set_localparam(const struct vlltype&loc,
bool signed_flag, list<pform_range_t>*range, PExpr*expr)
{
LexicalScope*scope = lexical_scope;
if ((scope == 0) && !gn_system_verilog()) {
if (is_compilation_unit(scope) && !gn_system_verilog()) {
VLerror(loc, "error: localparam declarations must be contained within a module.");
return;
}
if (scope == 0) {
VLerror(loc, "sorry: localparam declarations in the $root scope are not yet supported.");
return;
}
PScopeExtra*scopex = find_nearest_scopex(lexical_scope);
assert(scopex);
// Check if the localparam name is already in the dictionary.
if (scope->localparams.find(name) != scope->localparams.end()) {
@ -3170,14 +3099,14 @@ void pform_set_localparam(const struct vlltype&loc,
FILE_NAME(&tloc, loc);
cerr << tloc.get_fileline() << ": error: duplicate definition "
"for localparam '" << name << "' in '"
<< pform_cur_module.front()->mod_name() << "'." << endl;
<< scopex->pscope_name() << "'." << endl;
error_count += 1;
}
if (scope->parameters.find(name) != scope->parameters.end()) {
LineInfo tloc;
FILE_NAME(&tloc, loc);
cerr << tloc.get_fileline() << ": error: parameter and "
<< "localparam in '" << pform_cur_module.front()->mod_name()
<< "localparam in '" << scopex->pscope_name()
<< "' have the same name '" << name << "'." << endl;
error_count += 1;
}
@ -3188,7 +3117,7 @@ void pform_set_localparam(const struct vlltype&loc,
LineInfo tloc;
FILE_NAME(&tloc, loc);
cerr << tloc.get_fileline() << ": error: specparam and "
"localparam in '" << pform_cur_module.front()->mod_name()
"localparam in '" << scopex->pscope_name()
<< "' have the same name '" << name << "'." << endl;
error_count += 1;
}
@ -3456,9 +3385,9 @@ void pform_set_port_type(const struct vlltype&li,
delete attr;
}
static void pform_set_integer_2atom(uint64_t width, bool signed_flag, perm_string name, NetNet::Type net_type, list<named_pexpr_t>*attr)
static void pform_set_integer_2atom(const struct vlltype&li, uint64_t width, bool signed_flag, perm_string name, NetNet::Type net_type, list<named_pexpr_t>*attr)
{
PWire*cur = pform_get_make_wire_in_scope(name, net_type, NetNet::NOT_A_PORT, IVL_VT_BOOL);
PWire*cur = pform_get_make_wire_in_scope(li, name, net_type, NetNet::NOT_A_PORT, IVL_VT_BOOL);
assert(cur);
cur->set_signed(signed_flag);
@ -3472,12 +3401,12 @@ static void pform_set_integer_2atom(uint64_t width, bool signed_flag, perm_strin
pform_bind_attributes(cur->attributes, attr, true);
}
static void pform_set_integer_2atom(uint64_t width, bool signed_flag, list<perm_string>*names, NetNet::Type net_type, list<named_pexpr_t>*attr)
static void pform_set_integer_2atom(const struct vlltype&li, uint64_t width, bool signed_flag, 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 ) {
perm_string txt = *cur;
pform_set_integer_2atom(width, signed_flag, txt, net_type, attr);
pform_set_integer_2atom(li, width, signed_flag, txt, net_type, attr);
}
}
@ -3488,7 +3417,7 @@ template <class T> static void pform_set2_data_type(const struct vlltype&li, T*d
VLerror(li, "Compound type is not PACKED in this context.");
}
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(data_type);
pform_bind_attributes(net->attributes, attr, true);
@ -3502,11 +3431,11 @@ template <class T> static void pform_set2_data_type(const struct vlltype&li, T*d
}
}
static void pform_set_enum(enum_type_t*enum_type,
static void pform_set_enum(const struct vlltype&li, enum_type_t*enum_type,
perm_string name, NetNet::Type net_type,
std::list<named_pexpr_t>*attr)
{
PWire*cur = pform_get_make_wire_in_scope(name, net_type, NetNet::NOT_A_PORT, enum_type->base_type);
PWire*cur = pform_get_make_wire_in_scope(li, name, net_type, NetNet::NOT_A_PORT, enum_type->base_type);
assert(cur);
cur->set_signed(enum_type->signed_flag);
@ -3545,7 +3474,7 @@ static void pform_set_enum(const struct vlltype&li, enum_type_t*enum_type,
for (list<perm_string>::iterator cur = names->begin()
; cur != names->end() ; ++ cur) {
perm_string txt = *cur;
pform_set_enum(enum_type, txt, net_type, attr);
pform_set_enum(li, enum_type, txt, net_type, attr);
}
}
@ -3569,11 +3498,11 @@ void pform_set_data_type(const struct vlltype&li, data_type_t*data_type, list<pe
}
if (atom2_type_t*atom2_type = dynamic_cast<atom2_type_t*> (data_type)) {
pform_set_integer_2atom(atom2_type->type_code, atom2_type->signed_flag, names, net_type, attr);
pform_set_integer_2atom(li, atom2_type->type_code, atom2_type->signed_flag, names, net_type, attr);
}
else if (struct_type_t*struct_type = dynamic_cast<struct_type_t*> (data_type)) {
pform_set_struct_type(struct_type, names, net_type, attr);
pform_set_struct_type(li, struct_type, names, net_type, attr);
}
else if (enum_type_t*enum_type = dynamic_cast<enum_type_t*> (data_type)) {
@ -3594,7 +3523,7 @@ void pform_set_data_type(const struct vlltype&li, data_type_t*data_type, list<pe
}
else if (class_type_t*class_type = dynamic_cast<class_type_t*> (data_type)) {
pform_set_class_type(class_type, names, net_type, attr);
pform_set_class_type(li, class_type, names, net_type, attr);
}
else if (parray_type_t*array_type = dynamic_cast<parray_type_t*> (data_type)) {
@ -3602,7 +3531,7 @@ void pform_set_data_type(const struct vlltype&li, data_type_t*data_type, list<pe
}
else if (string_type_t*string_type = dynamic_cast<string_type_t*> (data_type)) {
pform_set_string_type(string_type, names, net_type, attr);
pform_set_string_type(li, string_type, names, net_type, attr);
} else {
VLerror(li, "internal error: Unexpected data_type.");
@ -3643,6 +3572,16 @@ vector<PWire*>* pform_make_udp_input_ports(list<perm_string>*names)
PProcess* pform_make_behavior(ivl_process_type_t type, Statement*st,
list<named_pexpr_t>*attr)
{
// Add an implicit @* around the statement for the always_comb and
// always_latch statements.
if ((type == IVL_PR_ALWAYS_COMB) || (type == IVL_PR_ALWAYS_LATCH)) {
PEventStatement *tmp = new PEventStatement(true);
tmp->set_file(st->get_file());
tmp->set_lineno(st->get_lineno());
tmp->set_statement(st);
st = tmp;
}
PProcess*pp = new PProcess(type, st);
// If we are in a part of the code where the meta-comment
@ -3662,8 +3601,10 @@ PProcess* pform_make_behavior(ivl_process_type_t type, Statement*st,
pform_put_behavior_in_scope(pp);
ivl_assert(*st, ! pform_cur_module.empty());
if (pform_cur_module.front()->program_block && type == IVL_PR_ALWAYS) {
cerr << st->get_fileline() << ": error: Always statements not allowed"
if (pform_cur_module.front()->program_block &&
((type == IVL_PR_ALWAYS) || (type == IVL_PR_ALWAYS_COMB) ||
(type == IVL_PR_ALWAYS_FF) || (type == IVL_PR_ALWAYS_LATCH))) {
cerr << st->get_fileline() << ": error: Always statements are not allowed"
<< " in program blocks." << endl;
error_count += 1;
}
@ -3715,31 +3656,72 @@ void pform_add_modport_port(const struct vlltype&loc,
FILE*vl_input = 0;
extern void reset_lexor();
int pform_parse(const char*path, FILE*file)
int pform_parse(const char*path)
{
vl_file = path;
if (file == 0) {
if (strcmp(path, "-") == 0) {
vl_input = stdin;
} else 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 (strcmp(path, "-") == 0)
vl_input = stdin;
else
vl_input = fopen(path, "r");
if (verbose_flag)
cerr << "Executing: " << cmdline << endl<< flush;
vl_input = popen(cmdline, "r");
if (vl_input == 0) {
cerr << "Unable to open " <<vl_file << "." << endl;
return 11;
cerr << "Unable to preprocess " << path << "." << endl;
return 1;
}
if (verbose_flag)
cerr << "...parsing output from preprocessor..." << endl << flush;
free(cmdline);
} else {
vl_input = file;
vl_input = fopen(path, "r");
if (vl_input == 0) {
cerr << "Unable to open " << path << "." << endl;
return 1;
}
}
if (pform_units.empty() || separate_compilation) {
char unit_name[20];
static unsigned nunits = 0;
if (separate_compilation)
sprintf(unit_name, "$unit#%u", ++nunits);
else
sprintf(unit_name, "$unit");
PPackage*unit = new PPackage(lex_strings.make(unit_name), 0);
unit->default_lifetime = LexicalScope::STATIC;
unit->set_file(filename_strings.make(path));
unit->set_lineno(1);
pform_units.push_back(unit);
pform_set_timescale(def_ts_units, def_ts_prec, 0, 0);
allow_timeunit_decl = true;
allow_timeprec_decl = true;
lexical_scope = unit;
}
reset_lexor();
error_count = 0;
warn_count = 0;
int rc = VLparse();
if (file == 0)
fclose(vl_input);
if (vl_input != stdin) {
if (ivlpp_string)
pclose(vl_input);
else
fclose(vl_input);
}
if (rc) {
cerr << "I give up." << endl;

26
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
@ -567,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;
@ -844,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 {
@ -1176,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;
@ -1706,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

@ -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_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-2017 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:
@ -1543,6 +1544,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 +2137,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 +2815,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-2017 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;

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,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-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
@ -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;
@ -465,6 +469,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;
case 'E':
case 'e':
case 'N':

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2011-2016 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
@ -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:

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-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
@ -1521,6 +1521,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 +2153,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 +2304,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

@ -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

@ -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

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2009-2015 Tony Bybell.
* Copyright (c) 2009-2017 Tony Bybell.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@ -168,7 +168,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 {

View File

@ -825,7 +825,7 @@ _next_match:
/* Match description too long : reduce it */
matchLength = (15-1) + (oMaxMatch-op) * 255;
}
//printf("offset %5i, matchLength%5i \n", (int)(ip-match), matchLength + MINMATCH);
/*printf("offset %5i, matchLength%5i \n", (int)(ip-match), matchLength + MINMATCH);*/
ip += MINMATCH + matchLength;
if (matchLength>=ML_MASK)

View File

@ -5,7 +5,7 @@
%{
/*
* Copyright (c) 2007-2014 Stephen Williams (steve@icarus.com)
* Copyright (c) 2007-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
@ -217,7 +217,7 @@ static void destroy_sdf_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 @@
/*
* 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
@ -1971,6 +1971,8 @@ static const char *pts_convert(int value)
{
const char *string;
switch (value) {
case 2: string = "100s"; break;
case 1: string = "10s"; break;
case 0: string = "1s"; break;
case -1: string = "100ms"; break;
case -2: string = "10ms"; break;

View File

@ -4,7 +4,7 @@
%{
/*
* Copyright (c) 1999-2009 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
@ -199,7 +199,7 @@ void destroy_readmem_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 @@
/*
* Copyright (c) 2007-2014 Stephen Williams (steve@icarus.com)
* Copyright (c) 2007-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
@ -289,7 +289,10 @@ static PLI_INT32 sys_sdf_annotate_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
FILE *sdf_fd;
char *fname = get_filename(callh, name, vpi_scan(argv));
if (fname == 0) return 0;
if (fname == 0) {
vpi_free_object(argv);
return 0;
}
sdf_fd = fopen(fname, "r");
if (sdf_fd == 0) {
@ -297,6 +300,8 @@ static PLI_INT32 sys_sdf_annotate_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
(int)vpi_get(vpiLineNo, callh));
vpi_printf("Unable to open SDF file \"%s\"."
" Skipping this annotation.\n", fname);
vpi_free_object(argv);
free(fname);
return 0;
}

View File

@ -6,7 +6,7 @@
%{
/*
* 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
@ -154,7 +154,7 @@ void destroy_tblmod_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 @@
/*
* Copyright (c) 2001-2015 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-2017 Stephen Williams (steve@icarus.com)
*
*/
@ -684,6 +684,8 @@ similar:
<label> .cmp/gt <wid>, <A>, <B>;
<label> .cmp/ge.s <wid>, <A>, <B>;
<label> .cmp/gt.s <wid>, <A>, <B>;
<label> .cmp/weq <wid>, <A>, <B>;
<label> .cmp/wne <wid>, <A>, <B>;
Whereas the arithmetic statements generate an output the width of
<wid>, the comparisons produce a single bit vector result. The plain

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
@ -868,6 +868,76 @@ void vvp_cmp_gt::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
recv_vec4_base_(ptr, bit, BIT4_0);
}
vvp_cmp_weq::vvp_cmp_weq(unsigned wid)
: vvp_arith_(wid)
{
}
void vvp_cmp_weq::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
vvp_context_t)
{
dispatch_operand_(ptr, bit);
vvp_vector4_t eeq (1);
eeq.set_bit(0, BIT4_1);
assert(op_a_.size() == op_b_.size());
for (unsigned idx = 0 ; idx < op_a_.size() ; idx += 1) {
vvp_bit4_t a = op_a_.value(idx);
vvp_bit4_t b = op_b_.value(idx);
if (b == BIT4_X)
continue;
else if (b == BIT4_Z)
continue;
else if (a == BIT4_X)
eeq.set_bit(0, BIT4_X);
else if (a == BIT4_Z)
eeq.set_bit(0, BIT4_X);
else if (a != b) {
eeq.set_bit(0, BIT4_0);
break;
}
}
vvp_net_t*net = ptr.ptr();
net->send_vec4(eeq, 0);
}
vvp_cmp_wne::vvp_cmp_wne(unsigned wid)
: vvp_arith_(wid)
{
}
void vvp_cmp_wne::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
vvp_context_t)
{
dispatch_operand_(ptr, bit);
vvp_vector4_t eeq (1);
eeq.set_bit(0, BIT4_0);
assert(op_a_.size() == op_b_.size());
for (unsigned idx = 0 ; idx < op_a_.size() ; idx += 1) {
vvp_bit4_t a = op_a_.value(idx);
vvp_bit4_t b = op_b_.value(idx);
if (b == BIT4_X)
continue;
else if (b == BIT4_Z)
continue;
else if (a == BIT4_X)
eeq.set_bit(0, BIT4_X);
else if (a == BIT4_Z)
eeq.set_bit(0, BIT4_X);
else if (a != b) {
eeq.set_bit(0, BIT4_1);
break;
}
}
vvp_net_t*net = ptr.ptr();
net->send_vec4(eeq, 0);
}
vvp_shiftl::vvp_shiftl(unsigned wid)
: vvp_arith_(wid)

View File

@ -1,7 +1,7 @@
#ifndef IVL_arith_H
#define IVL_arith_H
/*
* 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
@ -200,6 +200,24 @@ class vvp_cmp_ne : public vvp_arith_ {
};
class vvp_cmp_weq : public vvp_arith_ {
public:
explicit vvp_cmp_weq(unsigned wid);
void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
vvp_context_t);
};
class vvp_cmp_wne : public vvp_arith_ {
public:
explicit vvp_cmp_wne(unsigned wid);
void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit,
vvp_context_t);
};
/*
* This base class implements both GT and GE comparisons. The derived

View File

@ -1,7 +1,7 @@
#ifndef IVL_codes_H
#define IVL_codes_H
/*
* 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
@ -75,6 +75,8 @@ extern bool of_CMPIS(vthread_t thr, vvp_code_t code);
extern bool of_CMPSTR(vthread_t thr, vvp_code_t code);
extern bool of_CMPU(vthread_t thr, vvp_code_t code);
extern bool of_CMPIU(vthread_t thr, vvp_code_t code);
extern bool of_CMPWE(vthread_t thr, vvp_code_t code);
extern bool of_CMPWNE(vthread_t thr, vvp_code_t code);
extern bool of_CMPWR(vthread_t thr, vvp_code_t code);
extern bool of_CMPWS(vthread_t thr, vvp_code_t code);
extern bool of_CMPWU(vthread_t thr, vvp_code_t code);

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
@ -117,21 +117,23 @@ static const struct opcode_table_s opcode_table[] = {
{ "%cassign/vec4", of_CASSIGN_VEC4, 1,{OA_FUNC_PTR,OA_NONE, OA_NONE} },
{ "%cassign/vec4/off",of_CASSIGN_VEC4_OFF,2,{OA_FUNC_PTR,OA_BIT1, OA_NONE} },
{ "%cassign/wr", of_CASSIGN_WR, 1,{OA_FUNC_PTR,OA_NONE, OA_NONE} },
{ "%cast2", of_CAST2, 0, {OA_NONE, OA_NONE, OA_NONE} },
{ "%cmp/e", of_CMPE, 0, {OA_NONE, OA_NONE, OA_NONE} },
{ "%cmp/ne", of_CMPNE, 0, {OA_NONE, OA_NONE, OA_NONE} },
{ "%cmp/s", of_CMPS, 0, {OA_NONE, OA_NONE, OA_NONE} },
{ "%cmp/str",of_CMPSTR, 0, {OA_NONE, OA_NONE, OA_NONE} },
{ "%cmp/u", of_CMPU, 0, {OA_NONE, OA_NONE, OA_NONE} },
{ "%cmp/wr", of_CMPWR, 0, {OA_NONE, OA_NONE, OA_NONE} },
{ "%cmp/ws", of_CMPWS, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
{ "%cmp/wu", of_CMPWU, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
{ "%cmp/x", of_CMPX, 0, {OA_NONE, OA_NONE, OA_NONE} },
{ "%cmp/z", of_CMPZ, 0, {OA_NONE, OA_NONE, OA_NONE} },
{ "%cmpi/e", of_CMPIE, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%cmpi/ne",of_CMPINE, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%cmpi/s", of_CMPIS, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%cmpi/u", of_CMPIU, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%cast2", of_CAST2, 0, {OA_NONE, OA_NONE, OA_NONE} },
{ "%cmp/e", of_CMPE, 0, {OA_NONE, OA_NONE, OA_NONE} },
{ "%cmp/ne", of_CMPNE, 0, {OA_NONE, OA_NONE, OA_NONE} },
{ "%cmp/s", of_CMPS, 0, {OA_NONE, OA_NONE, OA_NONE} },
{ "%cmp/str", of_CMPSTR, 0, {OA_NONE, OA_NONE, OA_NONE} },
{ "%cmp/u", of_CMPU, 0, {OA_NONE, OA_NONE, OA_NONE} },
{ "%cmp/we", of_CMPWE, 0, {OA_NONE, OA_NONE, OA_NONE} },
{ "%cmp/wne", of_CMPWNE, 0, {OA_NONE, OA_NONE, OA_NONE} },
{ "%cmp/wr", of_CMPWR, 0, {OA_NONE, OA_NONE, OA_NONE} },
{ "%cmp/ws", of_CMPWS, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
{ "%cmp/wu", of_CMPWU, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
{ "%cmp/x", of_CMPX, 0, {OA_NONE, OA_NONE, OA_NONE} },
{ "%cmp/z", of_CMPZ, 0, {OA_NONE, OA_NONE, OA_NONE} },
{ "%cmpi/e", of_CMPIE, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%cmpi/ne", of_CMPINE, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%cmpi/s", of_CMPIS, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%cmpi/u", of_CMPIU, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%concat/str", of_CONCAT_STR, 0,{OA_NONE, OA_NONE, OA_NONE} },
{ "%concat/vec4", of_CONCAT_VEC4, 0,{OA_NONE, OA_NONE, OA_NONE} },
{ "%concati/str", of_CONCATI_STR, 1,{OA_STRING,OA_NONE, OA_NONE} },
@ -476,6 +478,7 @@ struct vvp_net_resolv_list_s: public resolv_list_s {
bool vvp_net_resolv_list_s::resolve(bool mes)
{
static bool t0_trigger_generated = false;
vvp_net_t*tmp = vvp_net_lookup(label());
if (tmp) {
@ -484,6 +487,25 @@ bool vvp_net_resolv_list_s::resolve(bool mes)
return true;
}
// This is a special label used to create a T0 trigger for the
// always_comb/latch processes.
if (! t0_trigger_generated && (strcmp(label(), "E_0x0") == 0)) {
// This should never happen, but if it does then the E_0x0
// event generation may need to be explictly generated in
// the compiler output instead of implicitly in this code.
assert(! vpip_peek_current_scope()->is_automatic());
t0_trigger_generated = true;
// Create a local event with no name for the T0 trigger
compile_named_event(strdup(label()), strcpy(new char [1],""), true);
tmp = vvp_net_lookup(label());
assert(tmp);
tmp->link(port);
// Create a trigger for the T0 event.
vvp_net_ptr_t ptr (tmp, 0);
schedule_t0_trigger(ptr);
return true;
}
if (mes)
fprintf(stderr, "unresolved vvp_net reference: %s\n", label());
@ -1402,6 +1424,38 @@ void compile_cmp_gt_r(char*label, unsigned argc, struct symb_s*argv)
make_arith(arith, label, argc, argv);
}
void compile_cmp_weq(char*label, long wid,
unsigned argc, struct symb_s*argv)
{
assert( wid > 0 );
if (argc != 2) {
fprintf(stderr, "%s .cmp/weq has wrong number of symbols\n",label);
compile_errors += 1;
return;
}
vvp_arith_ *arith = new vvp_cmp_weq(wid);
make_arith(arith, label, argc, argv);
}
void compile_cmp_wne(char*label, long wid,
unsigned argc, struct symb_s*argv)
{
assert( wid > 0 );
if (argc != 2) {
fprintf(stderr, "%s .cmp/wne has wrong number of symbols\n",label);
compile_errors += 1;
return;
}
vvp_arith_ *arith = new vvp_cmp_wne(wid);
make_arith(arith, label, argc, argv);
}
void compile_delay(char*label, unsigned width,
vvp_delay_t*delay, struct symb_s arg)

View File

@ -1,7 +1,7 @@
#ifndef IVL_compile_H
#define IVL_compile_H
/*
* 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
@ -195,6 +195,10 @@ extern void compile_cmp_ge(char*label, long width, bool signed_flag,
unsigned argc, struct symb_s*argv);
extern void compile_cmp_gt(char*label, long width, bool signed_flag,
unsigned argc, struct symb_s*argv);
extern void compile_cmp_weq(char*label, long width,
unsigned argc, struct symb_s*argv);
extern void compile_cmp_wne(char*label, long width,
unsigned argc, struct symb_s*argv);
extern void compile_arith_mult_r(char*label, unsigned argc,
struct symb_s*argv);
@ -414,7 +418,7 @@ extern void compile_ufunc_vec4(char*label, char*code, unsigned wid,
*/
extern void compile_event(char*label, char*type,
unsigned argc, struct symb_s*argv);
extern void compile_named_event(char*label, char*type);
extern void compile_named_event(char*label, char*type, bool local_flag=false);
/*
@ -552,7 +556,7 @@ extern void compile_island_cleanup(void);
extern void compile_island_tran(char*label);
extern void compile_island_tranif(int sense, char*island,
char*ba, char*bb, char*src);
char*ba, char*bb, char*src, bool resistive);
extern void compile_island_tranvp(char*island, char*ba, char*bb,
unsigned width, unsigned part, unsigned off);

View File

@ -5,3 +5,47 @@ uninitVar:vvp_net.cc:167
// These functions are not used by Icarus
// __libvpi_c_dummy_function()
unusedFunction:libvpi.c:24
// These functions are not used by Icarus
// vpi_chk_error()
unusedFunction:vpi_priv.cc:193
// vpi_compare_objects()
unusedFunction:vpi_priv.cc:209
// vpi_control()
unusedFunction:vpi_priv.cc:1556
// vpi_flush()
unusedFunction:vpi_priv.cc:1519
// vpi_fopen()
unusedFunction:vpi_mcd.cc:287
// vpi_get_file()
unusedFunction:vpi_mcd.cc:321
// vpi_get_systf_info()
unusedFunction:vpi_priv.cc:225
// vpi_get_time()
unusedFunction:vpi_priv.cc:532
// vpi_get_userdata()
unusedFunction:vpi_tasks.cc:1020
// vpi_get_vlog_info()
unusedFunction:vpi_priv.cc:561
// vpi_handle_by_index()
unusedFunction:vpi_priv.cc:1273
// vpi_handle_by_name()
unusedFunction:vpi_priv.cc:1356
// vpi_mcd_close()
unusedFunction:vpi_mcd.cc:111
// vpi_mcd_name()
unusedFunction:vpi_mcd.cc:138
// vpi_mcd_open()
unusedFunction:vpi_mcd.cc:153
// vpi_put_userdata()
unusedFunction:vpi_tasks.cc:1010
// vpi_register_cb()
unusedFunction:vpi_callback.cc:552
// vpi_register_systf()
unusedFunction:vpi_tasks.cc:990
// vpi_remove_cb()
unusedFunction:vpi_callback.cc:601
// vpi_sim_control()
unusedFunction:vpi_priv.cc:1548
// vpi_vprintf()
unusedFunction:vpi_priv.cc:1505

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2004-2014 Stephen Williams (steve@icarus.com)
* Copyright (c) 2004-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
@ -829,7 +829,7 @@ static void compile_event_or(char*label, unsigned argc, struct symb_s*argv)
* inputs, it is only accessed by behavioral trigger statements, which
* in vvp are %set instructions.
*/
void compile_named_event(char*label, char*name)
void compile_named_event(char*label, char*name, bool local_flag)
{
vvp_net_t*ptr = new vvp_net_t;
@ -842,7 +842,7 @@ void compile_named_event(char*label, char*name)
}
define_functor_symbol(label, ptr);
compile_vpi_symbol(label, obj);
vpip_attach_to_current_scope(obj);
if (! local_flag) vpip_attach_to_current_scope(obj);
free(label);
delete[] name;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008-2012 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
@ -45,14 +45,14 @@ struct vvp_island_branch_tran : public vvp_island_branch {
vvp_island_branch_tran(vvp_net_t*en__, bool active_high__,
unsigned width__, unsigned part__,
unsigned offset__);
unsigned offset__, bool resistive__);
bool run_test_enabled();
void run_resolution();
void run_output();
vvp_net_t*en;
unsigned width, part, offset;
bool active_high;
bool active_high, resistive;
tran_state_t state;
};
@ -60,9 +60,10 @@ vvp_island_branch_tran::vvp_island_branch_tran(vvp_net_t*en__,
bool active_high__,
unsigned width__,
unsigned part__,
unsigned offset__)
unsigned offset__,
bool resistive__)
: en(en__), width(width__), part(part__), offset(offset__),
active_high(active_high__)
active_high(active_high__), resistive(resistive__)
{
state = en__ ? tran_disabled : tran_enabled;
}
@ -235,7 +236,8 @@ bool vvp_island_branch_tran::run_test_enabled()
// input is 'x' or 'z'. We use the rules that are given for MOS switches.
inline vvp_vector8_t resolve_ambiguous(const vvp_vector8_t&a,
const vvp_vector8_t&b,
tran_state_t state)
tran_state_t state,
unsigned str_map[8])
{
assert(a.size() == b.size());
vvp_vector8_t out (a.size());
@ -243,6 +245,9 @@ inline vvp_vector8_t resolve_ambiguous(const vvp_vector8_t&a,
for (unsigned idx = 0 ; idx < out.size() ; idx += 1) {
vvp_scalar_t a_bit = a.value(idx);
vvp_scalar_t b_bit = b.value(idx);
b_bit = vvp_scalar_t(b_bit.value(),
str_map[b_bit.strength0()],
str_map[b_bit.strength1()]);
if (state == tran_unknown) {
switch (b_bit.value()) {
case BIT4_0:
@ -293,8 +298,8 @@ static void push_value_through_branch(const vvp_vector8_t&val,
// previously collected (and resolved) for the port.
if (branch->width == 0) {
// There are no part selects.
dst_port->value = resolve_ambiguous(dst_port->value, val,
branch->state);
dst_port->value = resolve_ambiguous(dst_port->value, val, branch->state,
vvp_switch_strength_map[branch->resistive]);
} else if (dst_ab == 1) {
// The other side is a strict subset (part select)
@ -396,7 +401,8 @@ void compile_island_tran(char*label)
compile_island_base(label, use_island);
}
void compile_island_tranif(int sense, char*island, char*pa, char*pb, char*pe)
void compile_island_tranif(int sense, char*island, char*pa, char*pb, char*pe,
bool resistive)
{
vvp_island*use_island = compile_find_island(island);
assert(use_island);
@ -413,7 +419,7 @@ void compile_island_tranif(int sense, char*island, char*pa, char*pb, char*pe)
vvp_island_branch_tran*br = new vvp_island_branch_tran(en,
sense ? true :
false,
0, 0, 0);
0, 0, 0, resistive);
use_island->add_branch(br, pa, pb);
@ -430,7 +436,7 @@ void compile_island_tranvp(char*island, char*pa, char*pb,
free(island);
vvp_island_branch_tran*br = new vvp_island_branch_tran(NULL, false,
wid, par, off);
wid, par, off, false);
use_island->add_branch(br, pa, pb);

View File

@ -4,7 +4,7 @@
%{
/*
* 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
@ -146,6 +146,8 @@ static char* strdupnew(char const *str)
".cmp/gt" { return K_CMP_GT; }
".cmp/gt.r" { return K_CMP_GT_R; }
".cmp/gt.s" { return K_CMP_GT_S; }
".cmp/weq" { return K_CMP_WEQ; }
".cmp/wne" { return K_CMP_WNE; }
".concat" { return K_CONCAT; }
".concat8" { return K_CONCAT8; }
".delay" { return K_DELAY; }
@ -194,6 +196,9 @@ static char* strdupnew(char const *str)
".reduce/xnor" { return K_REDUCE_XNOR; }
".repeat" { return K_REPEAT; }
".resolv" { return K_RESOLV; }
".rtran" { return K_RTRAN; }
".rtranif0" { return K_RTRANIF0; }
".rtranif1" { return K_RTRANIF1; }
".scope" { return K_SCOPE; }
".sfunc" { return K_SFUNC; }
".sfunc/e" { return K_SFUNC_E; }
@ -333,7 +338,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

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005-2016 Stephen Williams (steve@icarus.com)
* Copyright (c) 2005-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
@ -19,9 +19,10 @@
# include "npmos.h"
vvp_fun_pmos_::vvp_fun_pmos_(bool enable_invert)
vvp_fun_pmos_::vvp_fun_pmos_(bool enable_invert, bool resistive)
{
inv_en_ = enable_invert;
resistive_ = resistive;
}
@ -58,12 +59,18 @@ void vvp_fun_pmos_::recv_vec8_pv(vvp_net_ptr_t ptr, const vvp_vector8_t&bit,
void vvp_fun_pmos_::generate_output_(vvp_net_ptr_t ptr)
{
const unsigned*strength_map = vvp_switch_strength_map[resistive_];
vvp_vector8_t out (bit_.size());
for (unsigned idx = 0 ; idx < out.size() ; idx += 1) {
vvp_bit4_t b_en = en_.value(idx);
vvp_scalar_t b_bit = bit_.value(idx);
b_bit = vvp_scalar_t(b_bit.value(),
strength_map[b_bit.strength0()],
strength_map[b_bit.strength1()]);
switch (b_en) {
case BIT4_0:
out.set_bit(idx, b_bit);
@ -93,7 +100,7 @@ void vvp_fun_pmos_::generate_output_(vvp_net_ptr_t ptr)
vvp_fun_pmos::vvp_fun_pmos(bool enable_invert)
: vvp_fun_pmos_(enable_invert)
: vvp_fun_pmos_(enable_invert, false)
{
}
@ -112,7 +119,7 @@ void vvp_fun_pmos::recv_vec8(vvp_net_ptr_t ptr, const vvp_vector8_t&bit)
}
vvp_fun_rpmos::vvp_fun_rpmos(bool enable_invert)
: vvp_fun_pmos_(enable_invert)
: vvp_fun_pmos_(enable_invert, true)
{
}
@ -126,7 +133,7 @@ void vvp_fun_rpmos::recv_vec8(vvp_net_ptr_t ptr, const vvp_vector8_t&bit)
if (ptr.port() != 0)
return;
bit_ = resistive_reduction(bit);
bit_ = bit;
generate_output_(ptr);
}
@ -135,8 +142,9 @@ void vvp_fun_rpmos::recv_vec8(vvp_net_ptr_t ptr, const vvp_vector8_t&bit)
* CMOS primitive.
*/
vvp_fun_cmos_::vvp_fun_cmos_()
vvp_fun_cmos_::vvp_fun_cmos_(bool resistive)
{
resistive_ = resistive;
}
void vvp_fun_cmos_::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t &bit,
@ -175,6 +183,8 @@ void vvp_fun_cmos_::recv_vec8_pv(vvp_net_ptr_t ptr, const vvp_vector8_t&bit,
void vvp_fun_cmos_::generate_output_(vvp_net_ptr_t ptr)
{
const unsigned*strength_map = vvp_switch_strength_map[resistive_];
vvp_vector8_t out (bit_.size());
for (unsigned idx = 0 ; idx < out.size() ; idx += 1) {
@ -182,6 +192,10 @@ void vvp_fun_cmos_::generate_output_(vvp_net_ptr_t ptr)
vvp_bit4_t b_p_en = p_en_.value(idx);
vvp_scalar_t b_bit = bit_.value(idx);
b_bit = vvp_scalar_t(b_bit.value(),
strength_map[b_bit.strength0()],
strength_map[b_bit.strength1()]);
if (b_n_en == BIT4_1 || b_p_en == BIT4_0) {
out.set_bit(idx, b_bit);
} else if (b_n_en == BIT4_0 && b_p_en == BIT4_1) {
@ -206,7 +220,7 @@ void vvp_fun_cmos_::generate_output_(vvp_net_ptr_t ptr)
}
vvp_fun_cmos::vvp_fun_cmos()
: vvp_fun_cmos_()
: vvp_fun_cmos_(false)
{
}
@ -225,7 +239,7 @@ void vvp_fun_cmos::recv_vec8(vvp_net_ptr_t ptr, const vvp_vector8_t&bit)
}
vvp_fun_rcmos::vvp_fun_rcmos()
: vvp_fun_cmos_()
: vvp_fun_cmos_(true)
{
}
@ -239,6 +253,6 @@ void vvp_fun_rcmos::recv_vec8(vvp_net_ptr_t ptr, const vvp_vector8_t&bit)
if (ptr.port() != 0)
return;
bit_ = resistive_reduction(bit);
bit_ = bit;
generate_output_(ptr);
}

View File

@ -1,7 +1,7 @@
#ifndef IVL_npmos_H
#define IVL_npmos_H
/*
* Copyright (c) 2005-2016 Stephen Williams (steve@icarus.com)
* Copyright (c) 2005-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
@ -46,7 +46,7 @@
class vvp_fun_pmos_ : public vvp_net_fun_t {
public:
explicit vvp_fun_pmos_(bool enable_invert);
explicit vvp_fun_pmos_(bool enable_invert, bool resistive);
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
vvp_context_t);
@ -62,7 +62,7 @@ class vvp_fun_pmos_ : public vvp_net_fun_t {
vvp_vector8_t bit_;
vvp_vector4_t en_;
bool inv_en_;
bool inv_en_, resistive_;
};
class vvp_fun_pmos : public vvp_fun_pmos_ {
@ -109,7 +109,7 @@ class vvp_fun_rpmos : public vvp_fun_pmos_ {
class vvp_fun_cmos_ : public vvp_net_fun_t {
public:
explicit vvp_fun_cmos_();
explicit vvp_fun_cmos_(bool resistive);
void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t &bit,
vvp_context_t);
@ -126,6 +126,7 @@ class vvp_fun_cmos_ : public vvp_net_fun_t {
vvp_vector8_t bit_;
vvp_vector4_t n_en_;
vvp_vector4_t p_en_;
bool resistive_;
};
class vvp_fun_cmos : public vvp_fun_cmos_ {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2016 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-2017 Stephen Williams (steve@icarus.com)
*
*/
@ -302,6 +302,18 @@ The %cmp/ne and %cmpi/ne variants are the same as the %cmp/e and
eliminate the need for a %flag_inv instruction to implement != and !==
operations.
* %cmp/we
* %cmp/wne
These instructions perform a wild comparison of two vectors of equal
size. Two values are pulled from the top of the stack, and not replaced.
The results are written into flag bit 4. The comparisons work like eq/ne
except an x/z bit in the r-value will match any l-value bit.
The %cmp/wne variant is the same as %cmp/we, but the 4 flag is inverted
in order to eliminate the need for a %flag_inv instruction to implement
the !=? operator.
* %cmp/wr
Compare real values for equality and less-then. This opcode pops to
@ -1299,7 +1311,7 @@ table for the xor is:
/*
* Copyright (c) 2001-2009 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

View File

@ -1,7 +1,7 @@
%{
/*
* 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
@ -27,6 +27,7 @@
# include <cstdlib>
# include <cassert>
# include "ivl_alloc.h"
# include "version_base.h"
/*
* These are bits in the lexor.
@ -80,7 +81,7 @@ static struct __vpiModPath*modpath_dst = 0;
%token K_ARRAY K_ARRAY_2U K_ARRAY_2S K_ARRAY_I K_ARRAY_OBJ K_ARRAY_R K_ARRAY_S K_ARRAY_STR K_ARRAY_PORT
%token K_CAST_INT K_CAST_REAL K_CAST_REAL_S K_CAST_2
%token K_CLASS
%token K_CMP_EEQ K_CMP_EQ K_CMP_EQX K_CMP_EQZ
%token K_CMP_EEQ K_CMP_EQ K_CMP_EQX K_CMP_EQZ K_CMP_WEQ K_CMP_WNE
%token K_CMP_EQ_R K_CMP_NEE K_CMP_NE K_CMP_NE_R
%token K_CMP_GE K_CMP_GE_R K_CMP_GE_S K_CMP_GT K_CMP_GT_R K_CMP_GT_S
%token K_CONCAT K_CONCAT8 K_DEBUG K_DELAY K_DFF_N K_DFF_N_ACLR
@ -92,7 +93,8 @@ static struct __vpiModPath*modpath_dst = 0;
%token K_PARAM_STR K_PARAM_L K_PARAM_REAL K_PART K_PART_PV
%token K_PART_V K_PART_V_S K_PORT K_PORT_INFO K_PV K_REDUCE_AND K_REDUCE_OR K_REDUCE_XOR
%token K_REDUCE_NAND K_REDUCE_NOR K_REDUCE_XNOR K_REPEAT
%token K_RESOLV K_SCOPE K_SFUNC K_SFUNC_E K_SHIFTL K_SHIFTR K_SHIFTRS
%token K_RESOLV K_RTRAN K_RTRANIF0 K_RTRANIF1
%token K_SCOPE K_SFUNC K_SFUNC_E K_SHIFTL K_SHIFTR K_SHIFTRS
%token K_SUBSTITUTE
%token K_THREAD K_TIMESCALE K_TRAN K_TRANIF0 K_TRANIF1 K_TRANVP
%token K_UFUNC_REAL K_UFUNC_VEC4 K_UFUNC_E K_UDP K_UDP_C K_UDP_S
@ -475,6 +477,16 @@ statement
compile_cmp_gt($1, $3, true, obj.cnt, obj.vect);
}
| T_LABEL K_CMP_WEQ T_NUMBER ',' symbols ';'
{ struct symbv_s obj = $5;
compile_cmp_weq($1, $3, obj.cnt, obj.vect);
}
| T_LABEL K_CMP_WNE T_NUMBER ',' symbols ';'
{ struct symbv_s obj = $5;
compile_cmp_wne($1, $3, obj.cnt, obj.vect);
}
/* Delay nodes take a set of numbers or a set of inputs. The delay
node takes two form, one with an array of constants and a single
input, and another with an array of inputs. */
@ -698,9 +710,19 @@ statement
/* Port information for scopes... currently this is just meta-data for VPI queries */
| K_PORT_INFO T_NUMBER port_type T_NUMBER T_STRING
| K_PORT_INFO T_NUMBER port_type T_NUMBER T_STRING ';'
{ compile_port_info( $2 /* port_index */, $3, $4 /* width */,
$5 /*&name */ ); }
/* Unfortunately, older versions didn't check for a semicolon at the end of
.port_info statements.
To insure backwards compatablitly with old files, we have a duplicate rule
that doesn't require a semicolon. After version 11, this rule will be
disabled (and can safely be deleted. */
| K_PORT_INFO T_NUMBER port_type T_NUMBER T_STRING
{ if (VERSION_MAJOR > 11)
yyerror("syntax error");
compile_port_info( $2 /* port_index */, $3, $4 /* width */,
$5 /*&name */ ); }
| K_TIMESCALE T_NUMBER T_NUMBER';'
{ compile_timescale($2, $3); }
@ -849,14 +871,23 @@ statement
| T_LABEL K_EXPORT T_SYMBOL ';'
{ compile_island_export($1, $3); }
| K_RTRAN T_SYMBOL ',' T_SYMBOL T_SYMBOL ';'
{ compile_island_tranif(0, $2, $4, $5, 0, 1); }
| K_RTRANIF0 T_SYMBOL ',' T_SYMBOL T_SYMBOL ',' T_SYMBOL ';'
{ compile_island_tranif(0, $2, $4, $5, $7, 1); }
| K_RTRANIF1 T_SYMBOL ',' T_SYMBOL T_SYMBOL ',' T_SYMBOL ';'
{ compile_island_tranif(1, $2, $4, $5, $7, 1); }
| K_TRAN T_SYMBOL ',' T_SYMBOL T_SYMBOL ';'
{ compile_island_tranif(0, $2, $4, $5, 0); }
{ compile_island_tranif(0, $2, $4, $5, 0, 0); }
| K_TRANIF0 T_SYMBOL ',' T_SYMBOL T_SYMBOL ',' T_SYMBOL ';'
{ compile_island_tranif(0, $2, $4, $5, $7); }
{ compile_island_tranif(0, $2, $4, $5, $7, 0); }
| K_TRANIF1 T_SYMBOL ',' T_SYMBOL T_SYMBOL ',' T_SYMBOL ';'
{ compile_island_tranif(1, $2, $4, $5, $7); }
{ compile_island_tranif(1, $2, $4, $5, $7, 0); }
| K_TRANVP T_NUMBER T_NUMBER T_NUMBER ',' T_SYMBOL ',' T_SYMBOL T_SYMBOL ';'
{ compile_island_tranvp($6, $8, $9, $2, $3, $4); }

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
@ -76,6 +76,7 @@ struct event_time_s {
count_time_events += 1;
start = 0;
active = 0;
inactive = 0;
nbassign = 0;
rwsync = 0;
rosync = 0;
@ -86,6 +87,7 @@ struct event_time_s {
struct event_s*start;
struct event_s*active;
struct event_s*inactive;
struct event_s*nbassign;
struct event_s*rwsync;
struct event_s*rosync;
@ -661,14 +663,13 @@ static void schedule_final_event(struct event_s*cur)
* itself, and the structure is placed in the right place in the
* queue.
*/
typedef enum event_queue_e { SEQ_START, SEQ_ACTIVE, SEQ_NBASSIGN,
typedef enum event_queue_e { SEQ_START, SEQ_ACTIVE, SEQ_INACTIVE, SEQ_NBASSIGN,
SEQ_RWSYNC, SEQ_ROSYNC, DEL_THREAD } event_queue_t;
static void schedule_event_(struct event_s*cur, vvp_time64_t delay,
event_queue_t select_queue)
{
cur->next = cur;
struct event_time_s*ctim = sched_list;
if (sched_list == 0) {
@ -736,6 +737,11 @@ static void schedule_event_(struct event_s*cur, vvp_time64_t delay,
q = &ctim->active;
break;
case SEQ_INACTIVE:
assert(delay == 0);
q = &ctim->inactive;
break;
case SEQ_NBASSIGN:
q = &ctim->nbassign;
break;
@ -801,6 +807,23 @@ void schedule_vthread(vthread_t thr, vvp_time64_t delay, bool push_flag)
}
}
void schedule_t0_trigger(vvp_net_ptr_t ptr)
{
vvp_vector4_t bit (1, BIT4_X);
struct assign_vector4_event_s*cur = new struct assign_vector4_event_s(bit);
cur->ptr = ptr;
schedule_event_(cur, 0, SEQ_INACTIVE);
}
void schedule_inactive(vthread_t thr)
{
struct vthread_event_s*cur = new vthread_event_s;
cur->thr = thr;
vthread_mark_scheduled(thr);
schedule_event_(cur, 0, SEQ_INACTIVE);
}
void schedule_init_vthread(vthread_t thr)
{
struct vthread_event_s*cur = new vthread_event_s;
@ -1044,7 +1067,7 @@ static void run_rosync(struct event_time_s*ctim)
delete cur;
}
if (ctim->active || ctim->nbassign || ctim->rwsync) {
if (ctim->active || ctim->inactive || ctim->nbassign || ctim->rwsync) {
cerr << "SCHEDULER ERROR: read-only sync events "
<< "created RW events!" << endl;
}
@ -1145,21 +1168,26 @@ void schedule_simulate(void)
queues. If there are not events at all, then release
the event_time object. */
if (ctim->active == 0) {
ctim->active = ctim->nbassign;
ctim->nbassign = 0;
ctim->active = ctim->inactive;
ctim->inactive = 0;
if (ctim->active == 0) {
ctim->active = ctim->rwsync;
ctim->rwsync = 0;
ctim->active = ctim->nbassign;
ctim->nbassign = 0;
/* If out of rw events, then run the rosync
events and delete this time step. This also
deletes threads as needed. */
if (ctim->active == 0) {
run_rosync(ctim);
sched_list = ctim->next;
delete ctim;
continue;
ctim->active = ctim->rwsync;
ctim->rwsync = 0;
/* If out of rw events, then run the rosync
events and delete this time step. This also
deletes threads as needed. */
if (ctim->active == 0) {
run_rosync(ctim);
sched_list = ctim->next;
delete ctim;
continue;
}
}
}
}

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