Merge branch 'master' of github.com:steveicarus/iverilog
This commit is contained in:
commit
6c39348d1a
|
|
@ -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()
|
||||
|
|
|
|||
4
Module.h
4
Module.h
|
|
@ -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;
|
||||
|
|
|
|||
21
PDelays.cc
21
PDelays.cc
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
17
PScope.h
17
PScope.h
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
10
Statement.cc
10
Statement.cc
|
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
750
cppcheck.sup
750
cppcheck.sup
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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 ) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
76
elab_expr.cc
76
elab_expr.cc
|
|
@ -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: "
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
26
elab_sig.cc
26
elab_sig.cc
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
13
elab_type.cc
13
elab_type.cc
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
335
elaborate.cc
335
elaborate.cc
|
|
@ -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
20
emit.cc
|
|
@ -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);
|
||||
|
|
|
|||
158
eval_tree.cc
158
eval_tree.cc
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
1
ivl.def
1
ivl.def
|
|
@ -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
|
||||
|
|
|
|||
17
ivl_target.h
17
ivl_target.h
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
22
ivlpp/main.c
22
ivlpp/main.c
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
48
lexor.lex
48
lexor.lex
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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&);
|
||||
|
|
|
|||
|
|
@ -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
84
main.cc
|
|
@ -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);
|
||||
|
|
|
|||
207
net_design.cc
207
net_design.cc
|
|
@ -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);
|
||||
|
|
|
|||
10
net_event.cc
10
net_event.cc
|
|
@ -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_;
|
||||
}
|
||||
|
|
|
|||
343
net_nex_input.cc
343
net_nex_input.cc
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
45
net_scope.cc
45
net_scope.cc
|
|
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
|
|||
679
netlist.cc
679
netlist.cc
|
|
@ -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
211
netlist.h
|
|
@ -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.
|
||||
|
|
|
|||
39
netmisc.cc
39
netmisc.cc
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
12
netmisc.h
12
netmisc.h
|
|
@ -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
179
parse.y
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
23
parse_api.h
23
parse_api.h
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
552
pform.cc
|
|
@ -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
26
pform.h
|
|
@ -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¶m);
|
|||
*/
|
||||
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 */
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
11
syn-rules.y
11
syn-rules.y
|
|
@ -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;
|
||||
|
|
|
|||
5
synth.cc
5
synth.cc
|
|
@ -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:
|
||||
|
|
|
|||
25
t-dll-api.cc
25
t-dll-api.cc
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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*)
|
||||
|
|
|
|||
41
t-dll.cc
41
t-dll.cc
|
|
@ -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;
|
||||
|
|
|
|||
5
t-dll.h
5
t-dll.h
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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':
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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':
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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) );
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
72
vvp/arith.cc
72
vvp/arith.cc
|
|
@ -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)
|
||||
|
|
|
|||
20
vvp/arith.h
20
vvp/arith.h
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
32
vvp/npmos.cc
32
vvp/npmos.cc
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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_ {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
45
vvp/parse.y
45
vvp/parse.y
|
|
@ -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); }
|
||||
|
|
|
|||
|
|
@ -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
Loading…
Reference in New Issue