1998-11-04 00:28:49 +01:00
|
|
|
/*
|
2024-01-07 14:14:48 +01:00
|
|
|
* Copyright (c) 1998-2024 Stephen Williams (steve@icarus.com)
|
1998-11-04 00:28:49 +01:00
|
|
|
*
|
|
|
|
|
* This source code is free software; you can redistribute it
|
|
|
|
|
* and/or modify it in source code form under the terms of the GNU
|
|
|
|
|
* General Public License as published by the Free Software
|
|
|
|
|
* Foundation; either version 2 of the License, or (at your option)
|
|
|
|
|
* any later version.
|
|
|
|
|
*
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
|
* along with this program; if not, write to the Free Software
|
2012-08-29 03:41:23 +02:00
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
1998-11-04 00:28:49 +01:00
|
|
|
*/
|
|
|
|
|
|
2001-07-25 05:10:48 +02:00
|
|
|
# include "config.h"
|
|
|
|
|
|
|
|
|
|
# include <iostream>
|
|
|
|
|
|
1998-11-07 20:17:10 +01:00
|
|
|
# include <typeinfo>
|
2008-01-05 00:23:47 +01:00
|
|
|
# include <cstdlib>
|
2008-10-01 04:49:55 +02:00
|
|
|
# include <climits>
|
2017-12-28 08:07:29 +01:00
|
|
|
# include <cstring>
|
2003-03-01 07:25:30 +01:00
|
|
|
# include "compiler.h"
|
1998-11-04 00:28:49 +01:00
|
|
|
# include "netlist.h"
|
1999-10-05 06:02:10 +02:00
|
|
|
# include "netmisc.h"
|
2012-11-25 19:13:05 +01:00
|
|
|
# include "netclass.h"
|
2012-07-14 03:41:41 +02:00
|
|
|
# include "netdarray.h"
|
|
|
|
|
# include "netenum.h"
|
2012-09-30 00:13:45 +02:00
|
|
|
# include "netparray.h"
|
2022-01-09 00:27:56 +01:00
|
|
|
# include "netscalar.h"
|
2014-08-01 02:56:16 +02:00
|
|
|
# include "netqueue.h"
|
2011-12-11 19:28:04 +01:00
|
|
|
# include "netstruct.h"
|
2012-09-15 19:27:43 +02:00
|
|
|
# include "netvector.h"
|
2007-02-14 06:59:46 +01:00
|
|
|
# include "ivl_assert.h"
|
1998-11-04 00:28:49 +01:00
|
|
|
|
2021-11-04 17:12:04 +01:00
|
|
|
using namespace std;
|
2003-03-01 07:25:30 +01:00
|
|
|
|
1998-12-01 01:42:13 +01:00
|
|
|
ostream& operator<< (ostream&o, NetNet::Type t)
|
|
|
|
|
{
|
|
|
|
|
switch (t) {
|
2004-06-13 06:56:53 +02:00
|
|
|
case NetNet::NONE:
|
|
|
|
|
o << "net_none";
|
|
|
|
|
break;
|
1998-12-01 01:42:13 +01:00
|
|
|
case NetNet::IMPLICIT:
|
|
|
|
|
o << "wire /*implicit*/";
|
|
|
|
|
break;
|
1999-07-31 21:14:47 +02:00
|
|
|
case NetNet::IMPLICIT_REG:
|
|
|
|
|
o << "reg /*implicit*/";
|
|
|
|
|
break;
|
1998-12-01 01:42:13 +01:00
|
|
|
case NetNet::REG:
|
|
|
|
|
o << "reg";
|
|
|
|
|
break;
|
|
|
|
|
case NetNet::SUPPLY0:
|
|
|
|
|
o << "supply0";
|
|
|
|
|
break;
|
|
|
|
|
case NetNet::SUPPLY1:
|
|
|
|
|
o << "supply1";
|
|
|
|
|
break;
|
|
|
|
|
case NetNet::TRI:
|
|
|
|
|
o << "tri";
|
|
|
|
|
break;
|
|
|
|
|
case NetNet::TRI0:
|
|
|
|
|
o << "tri0";
|
|
|
|
|
break;
|
|
|
|
|
case NetNet::TRI1:
|
|
|
|
|
o << "tri1";
|
|
|
|
|
break;
|
|
|
|
|
case NetNet::TRIAND:
|
|
|
|
|
o << "triand";
|
|
|
|
|
break;
|
|
|
|
|
case NetNet::TRIOR:
|
|
|
|
|
o << "trior";
|
|
|
|
|
break;
|
|
|
|
|
case NetNet::WAND:
|
|
|
|
|
o << "wand";
|
|
|
|
|
break;
|
|
|
|
|
case NetNet::WOR:
|
|
|
|
|
o << "wor";
|
|
|
|
|
break;
|
|
|
|
|
case NetNet::WIRE:
|
|
|
|
|
o << "wire";
|
|
|
|
|
break;
|
2010-10-08 05:13:11 +02:00
|
|
|
case NetNet::UNRESOLVED_WIRE:
|
2009-06-02 02:19:56 +02:00
|
|
|
o << "uwire";
|
1998-12-01 01:42:13 +01:00
|
|
|
}
|
|
|
|
|
return o;
|
|
|
|
|
}
|
|
|
|
|
|
2000-05-07 06:37:55 +02:00
|
|
|
unsigned count_signals(const Link&pin)
|
1998-12-07 05:53:16 +01:00
|
|
|
{
|
|
|
|
|
unsigned count = 0;
|
|
|
|
|
|
2000-06-25 21:59:41 +02:00
|
|
|
const Nexus*nex = pin.nexus();
|
|
|
|
|
for (const Link*clnk = nex->first_nlink()
|
|
|
|
|
; clnk ; clnk = clnk->next_nlink()) {
|
2008-08-05 05:54:05 +02:00
|
|
|
const NetPins*cur;
|
2000-06-25 00:55:19 +02:00
|
|
|
unsigned cpin;
|
|
|
|
|
clnk->cur_link(cur, cpin);
|
1998-12-07 05:53:16 +01:00
|
|
|
if (dynamic_cast<const NetNet*>(cur))
|
|
|
|
|
count += 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return count;
|
|
|
|
|
}
|
|
|
|
|
|
1998-11-04 00:28:49 +01:00
|
|
|
const NetNet* find_link_signal(const NetObj*net, unsigned pin, unsigned&bidx)
|
|
|
|
|
{
|
2000-06-25 21:59:41 +02:00
|
|
|
const Nexus*nex = net->pin(pin).nexus();
|
|
|
|
|
|
|
|
|
|
for (const Link*clnk = nex->first_nlink()
|
|
|
|
|
; clnk ; clnk = clnk->next_nlink()) {
|
2000-06-25 00:55:19 +02:00
|
|
|
|
2008-08-05 05:54:05 +02:00
|
|
|
const NetPins*cur;
|
2000-06-25 00:55:19 +02:00
|
|
|
unsigned cpin;
|
|
|
|
|
clnk->cur_link(cur, cpin);
|
1998-11-04 00:28:49 +01:00
|
|
|
|
|
|
|
|
const NetNet*sig = dynamic_cast<const NetNet*>(cur);
|
|
|
|
|
if (sig) {
|
|
|
|
|
bidx = cpin;
|
|
|
|
|
return sig;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2000-05-07 06:37:55 +02:00
|
|
|
Link* find_next_output(Link*lnk)
|
1999-11-19 04:02:25 +01:00
|
|
|
{
|
2000-06-25 21:59:41 +02:00
|
|
|
Link*cur = lnk->next_nlink();
|
|
|
|
|
while (cur != lnk) {
|
2000-05-07 06:37:55 +02:00
|
|
|
if (cur->get_dir() == Link::OUTPUT)
|
1999-11-19 04:02:25 +01:00
|
|
|
return cur;
|
|
|
|
|
|
2000-06-25 21:59:41 +02:00
|
|
|
cur = cur->next_nlink();
|
|
|
|
|
if (cur == 0)
|
|
|
|
|
cur = lnk->nexus()->first_nlink();
|
|
|
|
|
}
|
|
|
|
|
|
1999-11-19 04:02:25 +01:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2009-03-06 02:44:11 +01:00
|
|
|
void NetPins::devirtualize_pins(void)
|
2001-07-01 02:27:34 +02:00
|
|
|
{
|
2009-03-06 02:44:11 +01:00
|
|
|
if (pins_) return;
|
2009-03-11 17:18:30 +01:00
|
|
|
if (npins_ > array_size_limit) {
|
|
|
|
|
cerr << get_fileline() << ": error: pin count " << npins_ <<
|
|
|
|
|
" exceeds " << array_size_limit <<
|
|
|
|
|
" (set by -pARRAY_SIZE_LIMIT)" << endl;
|
2023-04-13 22:00:34 +02:00
|
|
|
ivl_assert(*this, 0);
|
2009-03-11 17:18:30 +01:00
|
|
|
}
|
2009-03-06 02:44:11 +01:00
|
|
|
if (debug_optimizer && npins_ > 1000) cerr << "debug: devirtualizing " << npins_ << " pins." << endl;
|
|
|
|
|
|
2001-07-01 02:27:34 +02:00
|
|
|
pins_ = new Link[npins_];
|
2008-09-14 04:49:38 +02:00
|
|
|
pins_[0].pin_zero_ = true;
|
|
|
|
|
pins_[0].node_ = this;
|
2009-03-06 02:44:11 +01:00
|
|
|
pins_[0].dir_ = default_dir_;
|
2008-09-14 04:49:38 +02:00
|
|
|
|
|
|
|
|
for (unsigned idx = 1 ; idx < npins_ ; idx += 1) {
|
|
|
|
|
pins_[idx].pin_zero_ = false;
|
|
|
|
|
pins_[idx].pin_ = idx;
|
2009-03-06 02:44:11 +01:00
|
|
|
pins_[idx].dir_ = default_dir_;
|
2001-07-01 02:27:34 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-03-06 02:44:11 +01:00
|
|
|
bool NetPins::pins_are_virtual(void) const
|
|
|
|
|
{
|
|
|
|
|
return pins_ == NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NetPins::NetPins(unsigned npins)
|
|
|
|
|
: npins_(npins)
|
|
|
|
|
{
|
2015-10-18 02:06:12 +02:00
|
|
|
default_dir_ = Link::PASSIVE;
|
2009-03-06 02:44:11 +01:00
|
|
|
pins_ = NULL; // Wait until someone asks.
|
|
|
|
|
if (disable_virtual_pins) devirtualize_pins(); // Ask. Bummer.
|
|
|
|
|
}
|
|
|
|
|
|
2008-08-05 05:54:05 +02:00
|
|
|
NetPins::~NetPins()
|
1998-11-04 00:28:49 +01:00
|
|
|
{
|
2014-05-08 23:00:39 +02:00
|
|
|
if (pins_) {
|
2023-04-13 22:00:34 +02:00
|
|
|
ivl_assert(*this, pins_[0].node_ == this);
|
|
|
|
|
ivl_assert(*this, pins_[0].pin_zero_);
|
2014-05-08 23:00:39 +02:00
|
|
|
delete[] pins_;
|
|
|
|
|
}
|
1998-11-04 00:28:49 +01:00
|
|
|
}
|
|
|
|
|
|
2008-08-05 05:54:05 +02:00
|
|
|
Link& NetPins::pin(unsigned idx)
|
1999-09-13 05:10:59 +02:00
|
|
|
{
|
2009-03-06 02:44:11 +01:00
|
|
|
if (!pins_) devirtualize_pins();
|
2003-05-01 03:13:57 +02:00
|
|
|
if (idx >= npins_) {
|
2007-12-20 18:31:01 +01:00
|
|
|
cerr << get_fileline() << ": internal error: pin("<<idx<<")"
|
2003-05-01 03:13:57 +02:00
|
|
|
<< " out of bounds("<<npins_<<")" << endl;
|
2007-12-20 18:31:01 +01:00
|
|
|
cerr << get_fileline() << ": : typeid="
|
2003-05-01 03:13:57 +02:00
|
|
|
<< typeid(*this).name() << endl;
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-13 22:00:34 +02:00
|
|
|
ivl_assert(*this, idx < npins_);
|
|
|
|
|
ivl_assert(*this, idx == 0? (pins_[0].pin_zero_ && pins_[0].node_==this) : pins_[idx].pin_==idx);
|
2008-09-14 04:49:38 +02:00
|
|
|
|
1999-09-13 05:10:59 +02:00
|
|
|
return pins_[idx];
|
|
|
|
|
}
|
|
|
|
|
|
2008-08-05 05:54:05 +02:00
|
|
|
const Link& NetPins::pin(unsigned idx) const
|
1999-09-13 05:10:59 +02:00
|
|
|
{
|
2009-03-07 22:30:54 +01:00
|
|
|
if (!pins_ && !disable_virtual_pins) {
|
|
|
|
|
cerr << get_fileline() << ": internal error: pin is unexpectedly"
|
|
|
|
|
" virtual, try again with -pDISABLE_VIRTUAL_PINS=true" << endl;
|
2023-04-13 22:00:34 +02:00
|
|
|
ivl_assert(*this, 0);
|
2009-03-07 22:30:54 +01:00
|
|
|
}
|
2023-04-13 22:00:34 +02:00
|
|
|
ivl_assert(*this, pins_);
|
|
|
|
|
ivl_assert(*this, idx < npins_);
|
|
|
|
|
ivl_assert(*this, idx == 0? (pins_[0].pin_zero_ && pins_[0].node_==this) : pins_[idx].pin_==idx);
|
1999-09-13 05:10:59 +02:00
|
|
|
return pins_[idx];
|
|
|
|
|
}
|
|
|
|
|
|
2009-03-06 02:44:11 +01:00
|
|
|
void NetPins::set_default_dir(Link::DIR d)
|
|
|
|
|
{
|
|
|
|
|
default_dir_ = d;
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-14 01:42:04 +01:00
|
|
|
bool NetPins::is_linked(void) const
|
2009-01-12 16:28:37 +01:00
|
|
|
{
|
|
|
|
|
bool linked_flag = false;
|
|
|
|
|
if (pins_ == NULL) return false;
|
|
|
|
|
for (unsigned u = 0; u < npins_; u++) {
|
|
|
|
|
if (pins_[u].is_linked()) {
|
|
|
|
|
linked_flag = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return linked_flag;
|
|
|
|
|
}
|
|
|
|
|
|
2008-08-05 05:54:05 +02:00
|
|
|
NetObj::NetObj(NetScope*s, perm_string n, unsigned np)
|
|
|
|
|
: NetPins(np), scope_(s), name_(n), delay1_(0), delay2_(0), delay3_(0)
|
|
|
|
|
{
|
2010-10-02 20:02:27 +02:00
|
|
|
/* Don't
|
2009-03-11 17:18:30 +01:00
|
|
|
ivl_assert(*this, np > 0);
|
|
|
|
|
* because it would happen before we get to print a useful
|
|
|
|
|
* message in the NetNet constructor
|
|
|
|
|
*/
|
2008-08-05 05:54:05 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NetObj::~NetObj()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NetScope* NetObj::scope()
|
|
|
|
|
{
|
|
|
|
|
return scope_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const NetScope* NetObj::scope() const
|
|
|
|
|
{
|
|
|
|
|
return scope_;
|
|
|
|
|
}
|
|
|
|
|
|
2004-02-18 18:11:54 +01:00
|
|
|
NetNode::NetNode(NetScope*s, perm_string n, unsigned npins)
|
2001-07-01 02:27:34 +02:00
|
|
|
: NetObj(s, n, npins), node_next_(0), node_prev_(0), design_(0)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
1998-11-04 00:28:49 +01:00
|
|
|
NetNode::~NetNode()
|
|
|
|
|
{
|
|
|
|
|
if (design_)
|
|
|
|
|
design_->del_node(this);
|
|
|
|
|
}
|
|
|
|
|
|
2008-11-02 17:10:41 +01:00
|
|
|
NetBranch::NetBranch(ivl_discipline_t dis)
|
2008-11-10 00:32:50 +01:00
|
|
|
: NetPins(2), IslandBranch(dis)
|
2008-08-05 05:54:05 +02:00
|
|
|
{
|
|
|
|
|
pin(0).set_dir(Link::PASSIVE);
|
|
|
|
|
pin(1).set_dir(Link::PASSIVE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NetBranch::~NetBranch()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2008-10-06 18:53:39 +02:00
|
|
|
NetBus::NetBus(NetScope*s, unsigned pin_count__)
|
|
|
|
|
: NetObj(s, perm_string::literal(""), pin_count__)
|
2005-04-25 01:44:01 +02:00
|
|
|
{
|
2009-03-07 22:17:02 +01:00
|
|
|
for (unsigned idx = 0 ; idx <pin_count__ ; idx += 1) {
|
|
|
|
|
pin(idx).set_dir(Link::PASSIVE);
|
|
|
|
|
}
|
2005-04-25 01:44:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NetBus::~NetBus()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2013-08-24 03:22:32 +02:00
|
|
|
unsigned NetBus::find_link(const Link&that) const
|
|
|
|
|
{
|
|
|
|
|
unsigned ptr = 0;
|
|
|
|
|
|
|
|
|
|
while (ptr < pin_count()) {
|
|
|
|
|
if (pin(ptr).is_linked(that))
|
|
|
|
|
return ptr;
|
|
|
|
|
|
|
|
|
|
ptr += 1;
|
|
|
|
|
}
|
|
|
|
|
return ptr;
|
|
|
|
|
}
|
|
|
|
|
|
2008-04-29 04:00:29 +02:00
|
|
|
NetDelaySrc::NetDelaySrc(NetScope*s, perm_string n, unsigned npins,
|
2020-04-02 13:40:59 +02:00
|
|
|
bool condit_src, bool conditional, bool parallel)
|
2007-03-01 07:19:38 +01:00
|
|
|
: NetObj(s, n, npins + (condit_src?1:0))
|
2006-09-23 06:57:19 +02:00
|
|
|
{
|
2007-03-01 07:19:38 +01:00
|
|
|
condit_flag_ = false;
|
2008-04-29 04:00:29 +02:00
|
|
|
conditional_ = conditional;
|
2020-04-02 13:40:59 +02:00
|
|
|
parallel_ = parallel;
|
2007-03-02 07:13:22 +01:00
|
|
|
posedge_ = false;
|
|
|
|
|
negedge_ = false;
|
2006-09-23 06:57:19 +02:00
|
|
|
for (unsigned idx = 0 ; idx < npins ; idx += 1) {
|
|
|
|
|
pin(idx).set_dir(Link::INPUT);
|
|
|
|
|
}
|
2007-03-01 07:19:38 +01:00
|
|
|
|
|
|
|
|
if (condit_src) {
|
|
|
|
|
condit_flag_ = true;
|
|
|
|
|
pin(npins).set_dir(Link::INPUT);
|
|
|
|
|
}
|
2006-09-23 06:57:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NetDelaySrc::~NetDelaySrc()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void NetDelaySrc::set_delays(uint64_t del)
|
|
|
|
|
{
|
|
|
|
|
for (unsigned idx = 0 ; idx < 12 ; idx += 1)
|
|
|
|
|
transition_delays_[idx] = del;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void NetDelaySrc::set_delays(uint64_t trise, uint64_t tfall)
|
|
|
|
|
{
|
|
|
|
|
transition_delays_[IVL_PE_01] = trise;
|
|
|
|
|
transition_delays_[IVL_PE_10] = tfall;
|
|
|
|
|
transition_delays_[IVL_PE_0z] = trise;
|
|
|
|
|
transition_delays_[IVL_PE_z1] = trise;
|
|
|
|
|
transition_delays_[IVL_PE_1z] = tfall;
|
|
|
|
|
transition_delays_[IVL_PE_z0] = tfall;
|
|
|
|
|
transition_delays_[IVL_PE_0x] = trise;
|
|
|
|
|
transition_delays_[IVL_PE_x1] = trise;
|
|
|
|
|
transition_delays_[IVL_PE_1x] = tfall;
|
|
|
|
|
transition_delays_[IVL_PE_x0] = tfall;
|
|
|
|
|
transition_delays_[IVL_PE_xz] = max(trise,tfall);
|
|
|
|
|
transition_delays_[IVL_PE_zx] = min(trise,tfall);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void NetDelaySrc::set_delays(uint64_t trise, uint64_t tfall, uint64_t tz)
|
|
|
|
|
{
|
|
|
|
|
transition_delays_[IVL_PE_01] = trise;
|
|
|
|
|
transition_delays_[IVL_PE_10] = tfall;
|
|
|
|
|
transition_delays_[IVL_PE_0z] = tz;
|
|
|
|
|
transition_delays_[IVL_PE_z1] = trise;
|
|
|
|
|
transition_delays_[IVL_PE_1z] = tz;
|
|
|
|
|
transition_delays_[IVL_PE_z0] = tfall;
|
|
|
|
|
transition_delays_[IVL_PE_0x] = min(trise,tz);
|
|
|
|
|
transition_delays_[IVL_PE_x1] = trise;
|
|
|
|
|
transition_delays_[IVL_PE_1x] = min(tfall,tz);
|
|
|
|
|
transition_delays_[IVL_PE_x0] = tfall;
|
|
|
|
|
transition_delays_[IVL_PE_xz] = tz;
|
|
|
|
|
transition_delays_[IVL_PE_zx] = min(trise,tfall);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void NetDelaySrc::set_delays(uint64_t t01, uint64_t t10, uint64_t t0z,
|
|
|
|
|
uint64_t tz1, uint64_t t1z, uint64_t tz0)
|
|
|
|
|
{
|
|
|
|
|
transition_delays_[IVL_PE_01] = t01;
|
|
|
|
|
transition_delays_[IVL_PE_10] = t10;
|
|
|
|
|
transition_delays_[IVL_PE_0z] = t0z;
|
|
|
|
|
transition_delays_[IVL_PE_z1] = tz1;
|
|
|
|
|
transition_delays_[IVL_PE_1z] = t1z;
|
|
|
|
|
transition_delays_[IVL_PE_z0] = tz0;
|
|
|
|
|
transition_delays_[IVL_PE_0x] = min(t01,t0z);
|
|
|
|
|
transition_delays_[IVL_PE_x1] = max(t01,tz1);
|
|
|
|
|
transition_delays_[IVL_PE_1x] = min(t10,t1z);
|
|
|
|
|
transition_delays_[IVL_PE_x0] = max(t10,tz0);
|
|
|
|
|
transition_delays_[IVL_PE_xz] = max(t1z,t0z);
|
|
|
|
|
transition_delays_[IVL_PE_zx] = min(tz1,tz0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void NetDelaySrc::set_delays(uint64_t t01, uint64_t t10, uint64_t t0z,
|
|
|
|
|
uint64_t tz1, uint64_t t1z, uint64_t tz0,
|
|
|
|
|
uint64_t t0x, uint64_t tx1, uint64_t t1x,
|
|
|
|
|
uint64_t tx0, uint64_t txz, uint64_t tzx)
|
|
|
|
|
{
|
|
|
|
|
transition_delays_[IVL_PE_01] = t01;
|
|
|
|
|
transition_delays_[IVL_PE_10] = t10;
|
|
|
|
|
transition_delays_[IVL_PE_0z] = t0z;
|
|
|
|
|
transition_delays_[IVL_PE_z1] = tz1;
|
|
|
|
|
transition_delays_[IVL_PE_1z] = t1z;
|
|
|
|
|
transition_delays_[IVL_PE_z0] = tz0;
|
|
|
|
|
transition_delays_[IVL_PE_0x] = t0x;
|
|
|
|
|
transition_delays_[IVL_PE_x1] = tx1;
|
|
|
|
|
transition_delays_[IVL_PE_1x] = t1x;
|
|
|
|
|
transition_delays_[IVL_PE_x0] = tx0;
|
|
|
|
|
transition_delays_[IVL_PE_xz] = txz;
|
|
|
|
|
transition_delays_[IVL_PE_zx] = tzx;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint64_t NetDelaySrc::get_delay(unsigned idx) const
|
|
|
|
|
{
|
2023-04-13 22:00:34 +02:00
|
|
|
ivl_assert(*this, idx < 12);
|
2006-09-23 06:57:19 +02:00
|
|
|
return transition_delays_[idx];
|
|
|
|
|
}
|
|
|
|
|
|
2007-03-02 07:13:22 +01:00
|
|
|
void NetDelaySrc::set_posedge()
|
|
|
|
|
{
|
|
|
|
|
posedge_ = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void NetDelaySrc::set_negedge()
|
|
|
|
|
{
|
|
|
|
|
negedge_ = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool NetDelaySrc::is_posedge() const
|
|
|
|
|
{
|
|
|
|
|
return posedge_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool NetDelaySrc::is_negedge() const
|
|
|
|
|
{
|
|
|
|
|
return negedge_;
|
|
|
|
|
}
|
|
|
|
|
|
2007-03-01 07:19:38 +01:00
|
|
|
unsigned NetDelaySrc::src_count() const
|
|
|
|
|
{
|
|
|
|
|
if (condit_flag_)
|
|
|
|
|
return pin_count() - 1;
|
|
|
|
|
else
|
|
|
|
|
return pin_count();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Link& NetDelaySrc::src_pin(unsigned idx)
|
|
|
|
|
{
|
|
|
|
|
ivl_assert(*this, idx < src_count());
|
|
|
|
|
return pin(idx);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const Link& NetDelaySrc::src_pin(unsigned idx) const
|
|
|
|
|
{
|
|
|
|
|
ivl_assert(*this, idx < src_count());
|
|
|
|
|
return pin(idx);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool NetDelaySrc::is_condit() const
|
2008-04-29 04:00:29 +02:00
|
|
|
{
|
|
|
|
|
return conditional_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool NetDelaySrc::has_condit() const
|
2007-03-01 07:19:38 +01:00
|
|
|
{
|
|
|
|
|
return condit_flag_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Link& NetDelaySrc::condit_pin()
|
|
|
|
|
{
|
|
|
|
|
ivl_assert(*this, condit_flag_);
|
|
|
|
|
return pin(pin_count()-1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const Link& NetDelaySrc::condit_pin() const
|
|
|
|
|
{
|
|
|
|
|
ivl_assert(*this, condit_flag_);
|
|
|
|
|
return pin(pin_count()-1);
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-02 13:40:59 +02:00
|
|
|
bool NetDelaySrc::is_parallel() const
|
|
|
|
|
{
|
|
|
|
|
return parallel_;
|
|
|
|
|
}
|
|
|
|
|
|
2012-06-04 21:43:33 +02:00
|
|
|
PortType::Enum PortType::merged( Enum lhs, Enum rhs )
|
|
|
|
|
{
|
|
|
|
|
if( lhs == NOT_A_PORT || rhs == NOT_A_PORT )
|
|
|
|
|
return NOT_A_PORT;
|
|
|
|
|
if( lhs == PIMPLICIT )
|
|
|
|
|
return rhs;
|
|
|
|
|
if( rhs == PIMPLICIT )
|
|
|
|
|
return lhs;
|
|
|
|
|
if( lhs == rhs ) {
|
|
|
|
|
return lhs;
|
|
|
|
|
}
|
|
|
|
|
return PINOUT;
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-26 02:07:21 +02:00
|
|
|
void NetNet::initialize_dir_()
|
2009-01-12 16:28:37 +01:00
|
|
|
{
|
2013-10-26 02:07:21 +02:00
|
|
|
Link::DIR dir = Link::PASSIVE;
|
|
|
|
|
|
|
|
|
|
switch (type_) {
|
|
|
|
|
case REG:
|
|
|
|
|
case IMPLICIT_REG:
|
|
|
|
|
case SUPPLY0:
|
|
|
|
|
case SUPPLY1:
|
|
|
|
|
case TRI0:
|
|
|
|
|
case TRI1:
|
|
|
|
|
dir = Link::OUTPUT;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2009-03-06 02:44:11 +01:00
|
|
|
if (pins_are_virtual()) {
|
2009-12-11 22:44:29 +01:00
|
|
|
if (0) cerr << "NetNet setting Link default dir" << endl;
|
2009-03-06 02:44:11 +01:00
|
|
|
set_default_dir(dir);
|
|
|
|
|
} else {
|
2009-01-12 16:28:37 +01:00
|
|
|
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
|
|
|
|
|
pin(idx).set_dir(dir);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-06 15:41:18 +01:00
|
|
|
static unsigned calculate_count(const netranges_t &unpacked)
|
2007-01-16 06:44:14 +01:00
|
|
|
{
|
2022-01-06 15:41:18 +01:00
|
|
|
unsigned long sum = netrange_width(unpacked);
|
2012-05-26 00:58:29 +02:00
|
|
|
if (sum >= UINT_MAX)
|
2009-03-11 17:18:30 +01:00
|
|
|
return 0;
|
2012-05-26 00:58:29 +02:00
|
|
|
|
|
|
|
|
return sum;
|
2007-01-16 06:44:14 +01:00
|
|
|
}
|
|
|
|
|
|
2012-08-20 02:27:48 +02:00
|
|
|
void NetNet::calculate_slice_widths_from_packed_dims_(void)
|
|
|
|
|
{
|
2012-09-30 00:13:45 +02:00
|
|
|
ivl_assert(*this, net_type_);
|
2022-03-21 14:20:35 +01:00
|
|
|
if (!net_type_->packed())
|
|
|
|
|
return;
|
|
|
|
|
|
2012-09-30 00:13:45 +02:00
|
|
|
slice_dims_ = net_type_->slice_dimensions();
|
2012-09-15 19:27:43 +02:00
|
|
|
|
2012-09-30 00:13:45 +02:00
|
|
|
// Special case: There are no actual packed dimensions, so
|
|
|
|
|
// build up a fake dimension of "1".
|
2012-11-13 03:13:41 +01:00
|
|
|
if (slice_dims_.empty()) {
|
2012-09-30 00:13:45 +02:00
|
|
|
slice_wids_.resize(1);
|
|
|
|
|
slice_wids_[0] = net_type_->packed_width();
|
2012-08-20 02:27:48 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-30 00:13:45 +02:00
|
|
|
slice_wids_.resize(slice_dims_.size());
|
2012-08-20 02:27:48 +02:00
|
|
|
|
2012-11-13 03:13:41 +01:00
|
|
|
ivl_assert(*this, ! slice_wids_.empty());
|
2012-09-30 00:13:45 +02:00
|
|
|
slice_wids_[0] = netrange_width(slice_dims_);
|
2022-01-06 15:24:20 +01:00
|
|
|
netranges_t::const_iterator cur = slice_dims_.begin();
|
2016-09-14 08:44:44 +02:00
|
|
|
for (size_t idx = 1 ; idx < slice_wids_.size() ; idx += 1, ++cur) {
|
2012-08-20 02:27:48 +02:00
|
|
|
slice_wids_[idx] = slice_wids_[idx-1] / cur->width();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2007-01-16 06:44:14 +01:00
|
|
|
NetNet::NetNet(NetScope*s, perm_string n, Type t,
|
2022-01-06 15:41:18 +01:00
|
|
|
const netranges_t&unpacked, ivl_type_t use_net_type)
|
2012-05-26 00:58:29 +02:00
|
|
|
: NetObj(s, n, calculate_count(unpacked)),
|
2024-02-02 23:00:57 +01:00
|
|
|
type_(t), port_type_(NOT_A_PORT), coerced_to_uwire_(false),
|
2012-09-23 18:28:49 +02:00
|
|
|
local_flag_(false), net_type_(use_net_type),
|
2022-01-06 15:41:18 +01:00
|
|
|
discipline_(0), unpacked_dims_(unpacked),
|
2009-12-10 22:20:38 +01:00
|
|
|
eref_count_(0), lref_count_(0)
|
1999-04-19 03:59:36 +02:00
|
|
|
{
|
2012-08-20 02:27:48 +02:00
|
|
|
calculate_slice_widths_from_packed_dims_();
|
2012-05-26 00:58:29 +02:00
|
|
|
|
2009-03-11 17:18:30 +01:00
|
|
|
ivl_assert(*this, s);
|
|
|
|
|
if (pin_count() == 0) {
|
2012-07-14 03:41:41 +02:00
|
|
|
cerr << "Invalid array dimensions: " << unpacked << endl;
|
2009-03-11 17:18:30 +01:00
|
|
|
ivl_assert(*this, 0);
|
|
|
|
|
}
|
2000-05-02 02:58:11 +02:00
|
|
|
|
2013-10-26 02:07:21 +02:00
|
|
|
initialize_dir_();
|
2000-05-02 02:58:11 +02:00
|
|
|
|
2023-02-05 06:18:13 +01:00
|
|
|
if (!unpacked_dims_.empty())
|
|
|
|
|
array_type_ = new netuarray_t(unpacked_dims_, net_type_);
|
|
|
|
|
|
2000-10-07 01:46:50 +02:00
|
|
|
s->add_signal(this);
|
1999-04-19 03:59:36 +02:00
|
|
|
}
|
|
|
|
|
|
2022-03-21 14:20:35 +01:00
|
|
|
NetNet::NetNet(NetScope*s, perm_string n, Type t, ivl_type_t type)
|
2012-09-15 19:27:43 +02:00
|
|
|
: NetObj(s, n, 1),
|
2024-02-02 23:00:57 +01:00
|
|
|
type_(t), port_type_(NOT_A_PORT), coerced_to_uwire_(false),
|
2022-03-21 14:20:35 +01:00
|
|
|
local_flag_(false), net_type_(type),
|
2012-09-15 19:27:43 +02:00
|
|
|
discipline_(0),
|
|
|
|
|
eref_count_(0), lref_count_(0)
|
|
|
|
|
{
|
|
|
|
|
calculate_slice_widths_from_packed_dims_();
|
|
|
|
|
|
2013-10-26 02:07:21 +02:00
|
|
|
initialize_dir_();
|
2012-09-15 19:27:43 +02:00
|
|
|
|
|
|
|
|
s->add_signal(this);
|
|
|
|
|
}
|
|
|
|
|
|
1998-11-04 00:28:49 +01:00
|
|
|
NetNet::~NetNet()
|
|
|
|
|
{
|
2000-11-30 00:16:18 +01:00
|
|
|
if (eref_count_ > 0) {
|
2007-12-20 18:31:01 +01:00
|
|
|
cerr << get_fileline() << ": internal error: attempt to delete "
|
2000-11-30 00:16:18 +01:00
|
|
|
<< "signal ``" << name() << "'' which has "
|
|
|
|
|
<< "expression references." << endl;
|
|
|
|
|
dump_net(cerr, 4);
|
|
|
|
|
}
|
2023-04-13 22:00:34 +02:00
|
|
|
ivl_assert(*this, eref_count_ == 0);
|
2002-05-26 03:39:02 +02:00
|
|
|
if (lref_count_ > 0) {
|
2007-12-20 18:31:01 +01:00
|
|
|
cerr << get_fileline() << ": internal error: attempt to delete "
|
2002-05-26 03:39:02 +02:00
|
|
|
<< "signal ``" << name() << "'' which has "
|
|
|
|
|
<< "assign references." << endl;
|
|
|
|
|
dump_net(cerr, 4);
|
|
|
|
|
}
|
2023-04-13 22:00:34 +02:00
|
|
|
ivl_assert(*this, lref_count_ == 0);
|
2000-10-07 01:46:50 +02:00
|
|
|
if (scope())
|
|
|
|
|
scope()->rem_signal(this);
|
2002-08-19 02:06:11 +02:00
|
|
|
|
1999-11-27 20:07:57 +01:00
|
|
|
}
|
|
|
|
|
|
2000-09-24 17:44:44 +02:00
|
|
|
NetNet::Type NetNet::type() const
|
|
|
|
|
{
|
|
|
|
|
return type_;
|
|
|
|
|
}
|
|
|
|
|
|
2002-07-02 05:02:57 +02:00
|
|
|
void NetNet::type(NetNet::Type t)
|
|
|
|
|
{
|
|
|
|
|
if (type_ == t)
|
|
|
|
|
return;
|
|
|
|
|
|
2024-02-02 23:00:57 +01:00
|
|
|
if ((t == UNRESOLVED_WIRE) && ((type_ == REG) || (type_ == IMPLICIT_REG)))
|
|
|
|
|
coerced_to_uwire_ = true;
|
|
|
|
|
|
2002-07-02 05:02:57 +02:00
|
|
|
type_ = t;
|
2004-10-04 03:10:51 +02:00
|
|
|
|
2013-10-26 02:07:21 +02:00
|
|
|
initialize_dir_();
|
2002-07-02 05:02:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2000-09-24 17:44:44 +02:00
|
|
|
NetNet::PortType NetNet::port_type() const
|
|
|
|
|
{
|
|
|
|
|
return port_type_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void NetNet::port_type(NetNet::PortType t)
|
|
|
|
|
{
|
|
|
|
|
port_type_ = t;
|
|
|
|
|
}
|
|
|
|
|
|
2012-06-04 21:43:33 +02:00
|
|
|
int NetNet::get_module_port_index() const
|
|
|
|
|
{
|
|
|
|
|
return port_index_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void NetNet::set_module_port_index(unsigned idx)
|
|
|
|
|
{
|
|
|
|
|
port_index_ = idx;
|
2023-04-13 22:00:34 +02:00
|
|
|
ivl_assert(*this, port_index_ >= 0);
|
2012-06-04 21:43:33 +02:00
|
|
|
}
|
|
|
|
|
|
2012-09-15 19:27:43 +02:00
|
|
|
ivl_variable_type_t NetNet::data_type() const
|
2005-07-07 18:22:49 +02:00
|
|
|
{
|
2013-09-29 03:31:22 +02:00
|
|
|
ivl_assert(*this, net_type_);
|
|
|
|
|
return net_type_->base_type();
|
2005-07-07 18:22:49 +02:00
|
|
|
}
|
|
|
|
|
|
2000-12-11 01:31:43 +01:00
|
|
|
bool NetNet::get_signed() const
|
|
|
|
|
{
|
2013-09-29 03:31:22 +02:00
|
|
|
ivl_assert(*this, net_type_);
|
|
|
|
|
return net_type_->get_signed();
|
2000-12-11 01:31:43 +01:00
|
|
|
}
|
|
|
|
|
|
2009-04-15 01:08:27 +02:00
|
|
|
bool NetNet::get_scalar() const
|
|
|
|
|
{
|
2022-03-19 14:46:18 +01:00
|
|
|
ivl_assert(*this, net_type_);
|
|
|
|
|
return net_type_->get_scalar();
|
2009-04-15 01:08:27 +02:00
|
|
|
}
|
|
|
|
|
|
2013-04-15 03:03:21 +02:00
|
|
|
const netenum_t*NetNet::enumeration(void) const
|
2010-11-03 04:16:42 +01:00
|
|
|
{
|
2013-04-15 03:03:21 +02:00
|
|
|
return dynamic_cast<const netenum_t*> (net_type_);
|
2010-11-03 04:16:42 +01:00
|
|
|
}
|
|
|
|
|
|
2012-09-30 00:13:45 +02:00
|
|
|
const netstruct_t*NetNet::struct_type(void) const
|
2010-11-03 04:16:42 +01:00
|
|
|
{
|
2013-04-15 03:03:21 +02:00
|
|
|
ivl_type_t cur_type = net_type_;
|
2012-09-30 00:13:45 +02:00
|
|
|
while (cur_type) {
|
|
|
|
|
if (const netdarray_t*da = dynamic_cast<const netdarray_t*> (cur_type)) {
|
|
|
|
|
cur_type = da->element_type();
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (const netparray_t*da = dynamic_cast<const netparray_t*> (cur_type)) {
|
|
|
|
|
cur_type = da->element_type();
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (const netstruct_t*st = dynamic_cast<const netstruct_t*> (cur_type))
|
|
|
|
|
return st;
|
|
|
|
|
else
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-13 22:00:34 +02:00
|
|
|
ivl_assert(*this, 0);
|
2012-09-30 00:13:45 +02:00
|
|
|
return 0;
|
2010-11-03 04:16:42 +01:00
|
|
|
}
|
|
|
|
|
|
2013-04-15 03:03:21 +02:00
|
|
|
const netdarray_t* NetNet::darray_type(void) const
|
2011-12-04 02:16:01 +01:00
|
|
|
{
|
2013-04-15 03:03:21 +02:00
|
|
|
return dynamic_cast<const netdarray_t*> (net_type_);
|
2011-12-04 02:16:01 +01:00
|
|
|
}
|
|
|
|
|
|
2014-08-01 02:56:16 +02:00
|
|
|
const netqueue_t* NetNet::queue_type(void) const
|
|
|
|
|
{
|
|
|
|
|
return dynamic_cast<const netqueue_t*> (net_type_);
|
|
|
|
|
}
|
|
|
|
|
|
2013-04-15 03:03:21 +02:00
|
|
|
const netclass_t* NetNet::class_type(void) const
|
2012-11-25 19:13:05 +01:00
|
|
|
{
|
2013-04-15 03:03:21 +02:00
|
|
|
return dynamic_cast<const netclass_t*> (net_type_);
|
2012-11-25 19:13:05 +01:00
|
|
|
}
|
|
|
|
|
|
2023-02-05 06:18:13 +01:00
|
|
|
const netarray_t* NetNet::array_type() const
|
|
|
|
|
{
|
|
|
|
|
if (array_type_)
|
|
|
|
|
return array_type_;
|
|
|
|
|
|
|
|
|
|
return darray_type();
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-20 02:27:48 +02:00
|
|
|
/*
|
|
|
|
|
* "depth" is the number of index expressions that the user is using
|
2014-01-29 00:50:27 +01:00
|
|
|
* to index this identifier. So consider if Net was declared like so:
|
2012-08-20 02:27:48 +02:00
|
|
|
*
|
|
|
|
|
* reg [5:0][3:0] foo;
|
|
|
|
|
*
|
|
|
|
|
* In this case, slice_width(2) == 1 (slice_width(N) where N is the
|
|
|
|
|
* number of dimensions will always be 1.) and represents
|
|
|
|
|
* $bits(foo[a][b]). Then, slice_width(1)==4 ($bits(foo[a]) and slice_width(0)==24.
|
2014-04-06 05:57:22 +02:00
|
|
|
*
|
|
|
|
|
* NOTE: The caller should already have accounted for unpacked
|
|
|
|
|
* dimensions. The "depth" is only for the packed dimensions.
|
2012-08-20 02:27:48 +02:00
|
|
|
*/
|
|
|
|
|
unsigned long NetNet::slice_width(size_t depth) const
|
2012-08-06 01:28:40 +02:00
|
|
|
{
|
2012-08-20 02:27:48 +02:00
|
|
|
if (depth > slice_wids_.size())
|
|
|
|
|
return 0;
|
|
|
|
|
if (depth == slice_wids_.size())
|
|
|
|
|
return 1;
|
|
|
|
|
return slice_wids_[depth];
|
2012-08-06 01:28:40 +02:00
|
|
|
}
|
|
|
|
|
|
2008-11-02 17:10:41 +01:00
|
|
|
ivl_discipline_t NetNet::get_discipline() const
|
2008-08-05 05:54:05 +02:00
|
|
|
{
|
|
|
|
|
return discipline_;
|
|
|
|
|
}
|
|
|
|
|
|
2008-11-02 17:10:41 +01:00
|
|
|
void NetNet::set_discipline(ivl_discipline_t dis)
|
2008-08-05 05:54:05 +02:00
|
|
|
{
|
|
|
|
|
ivl_assert(*this, discipline_ == 0);
|
|
|
|
|
discipline_ = dis;
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-11 02:17:59 +01:00
|
|
|
bool NetNet::sb_is_valid(const list<long>&indices, long sb) const
|
2003-05-01 03:13:57 +02:00
|
|
|
{
|
2012-09-15 19:27:43 +02:00
|
|
|
ivl_assert(*this, indices.size()+1 == packed_dims().size());
|
2023-04-13 22:00:34 +02:00
|
|
|
ivl_assert(*this, packed_dims().size() == 1);
|
2012-09-15 19:27:43 +02:00
|
|
|
const netrange_t&rng = packed_dims().back();
|
2012-07-14 03:41:41 +02:00
|
|
|
if (rng.get_msb() >= rng.get_lsb())
|
|
|
|
|
return (sb <= rng.get_msb()) && (sb >= rng.get_lsb());
|
2003-05-01 03:13:57 +02:00
|
|
|
else
|
2012-07-14 03:41:41 +02:00
|
|
|
return (sb <= rng.get_lsb()) && (sb >= rng.get_msb());
|
2003-05-01 03:13:57 +02:00
|
|
|
}
|
|
|
|
|
|
2012-02-11 02:17:59 +01:00
|
|
|
long NetNet::sb_to_idx(const list<long>&indices, long sb) const
|
1999-09-13 05:10:59 +02:00
|
|
|
{
|
2012-09-15 19:27:43 +02:00
|
|
|
ivl_assert(*this, indices.size()+1 == packed_dims().size());
|
2012-02-11 03:48:12 +01:00
|
|
|
|
2022-01-06 15:24:20 +01:00
|
|
|
netranges_t::const_iterator pcur = packed_dims().end();
|
2012-02-11 03:48:12 +01:00
|
|
|
-- pcur;
|
|
|
|
|
|
|
|
|
|
long acc_off;
|
|
|
|
|
long acc_wid = pcur->width();
|
2012-07-14 03:41:41 +02:00
|
|
|
if (pcur->get_msb() >= pcur->get_lsb())
|
|
|
|
|
acc_off = sb - pcur->get_lsb();
|
1999-09-13 05:10:59 +02:00
|
|
|
else
|
2012-07-14 03:41:41 +02:00
|
|
|
acc_off = pcur->get_lsb() - sb;
|
2012-02-11 03:48:12 +01:00
|
|
|
|
2014-01-31 01:16:19 +01:00
|
|
|
// The acc_off is the position within the innermost
|
2012-02-11 03:48:12 +01:00
|
|
|
// dimension. If this is a multi-dimension packed array then
|
|
|
|
|
// we need to add in the canonical address of the current slice.
|
2012-11-13 03:13:41 +01:00
|
|
|
if (! indices.empty()) {
|
2012-02-11 03:48:12 +01:00
|
|
|
list<long>::const_iterator icur = indices.end();
|
|
|
|
|
do {
|
|
|
|
|
-- icur;
|
|
|
|
|
-- pcur;
|
|
|
|
|
|
|
|
|
|
long tmp_off;
|
2012-07-14 03:41:41 +02:00
|
|
|
if (pcur->get_msb() >= pcur->get_lsb())
|
|
|
|
|
tmp_off = *icur - pcur->get_lsb();
|
2012-02-11 03:48:12 +01:00
|
|
|
else
|
2012-07-14 03:41:41 +02:00
|
|
|
tmp_off = pcur->get_lsb() - *icur;
|
2012-02-11 03:48:12 +01:00
|
|
|
|
|
|
|
|
acc_off += tmp_off * acc_wid;
|
|
|
|
|
acc_wid *= pcur->width();
|
|
|
|
|
|
|
|
|
|
} while (icur != indices.begin());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return acc_off;
|
1999-09-13 05:10:59 +02:00
|
|
|
}
|
|
|
|
|
|
2012-02-11 02:17:59 +01:00
|
|
|
bool NetNet::sb_to_slice(const list<long>&indices, long sb, long&loff, unsigned long&lwid) const
|
|
|
|
|
{
|
2012-09-15 19:27:43 +02:00
|
|
|
ivl_assert(*this, indices.size() < packed_dims().size());
|
|
|
|
|
return prefix_to_slice(packed_dims(), indices, sb, loff, lwid);
|
2012-02-11 02:17:59 +01:00
|
|
|
}
|
|
|
|
|
|
2012-05-26 00:58:29 +02:00
|
|
|
unsigned NetNet::unpacked_count() const
|
2007-01-16 06:44:14 +01:00
|
|
|
{
|
2022-05-15 22:41:47 +02:00
|
|
|
return netrange_width(unpacked_dims_);
|
2007-01-16 06:44:14 +01:00
|
|
|
}
|
|
|
|
|
|
1999-11-29 00:42:02 +01:00
|
|
|
void NetNet::incr_eref()
|
|
|
|
|
{
|
|
|
|
|
eref_count_ += 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void NetNet::decr_eref()
|
|
|
|
|
{
|
2023-04-13 22:00:34 +02:00
|
|
|
ivl_assert(*this, eref_count_ > 0);
|
1999-11-29 00:42:02 +01:00
|
|
|
eref_count_ -= 1;
|
|
|
|
|
}
|
|
|
|
|
|
2002-05-26 03:39:02 +02:00
|
|
|
unsigned NetNet::peek_eref() const
|
1999-11-29 00:42:02 +01:00
|
|
|
{
|
|
|
|
|
return eref_count_;
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-03 18:55:32 +01:00
|
|
|
/*
|
|
|
|
|
* Test each of the bits in the range. If any bits are set then return true.
|
|
|
|
|
*/
|
|
|
|
|
bool NetNet::test_part_driven(unsigned pmsb, unsigned plsb, int widx)
|
|
|
|
|
{
|
|
|
|
|
if (lref_mask_.empty())
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
// If indexing a word that doesn't exist, then pretend this is
|
|
|
|
|
// never driven.
|
|
|
|
|
if (widx < 0)
|
|
|
|
|
return false;
|
|
|
|
|
if (widx >= (int)pin_count())
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
unsigned word_base = vector_width() * widx;
|
|
|
|
|
for (unsigned idx = plsb ; idx <= pmsb ; idx += 1) {
|
|
|
|
|
if (lref_mask_[idx+word_base])
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2012-01-28 19:20:09 +01:00
|
|
|
/*
|
|
|
|
|
* Test each of the bits in the range, and set them. If any bits are
|
|
|
|
|
* already set then return true.
|
|
|
|
|
*/
|
2014-03-29 04:51:30 +01:00
|
|
|
bool NetNet::test_and_set_part_driver(unsigned pmsb, unsigned plsb, int widx)
|
2012-01-28 19:20:09 +01:00
|
|
|
{
|
2012-08-08 20:26:46 +02:00
|
|
|
if (lref_mask_.empty())
|
2014-03-29 04:51:30 +01:00
|
|
|
lref_mask_.resize(vector_width() * pin_count());
|
|
|
|
|
|
|
|
|
|
// If indexing a word that doesn't exist, then pretend this is
|
|
|
|
|
// never driven.
|
|
|
|
|
if (widx < 0)
|
|
|
|
|
return false;
|
|
|
|
|
if (widx >= (int)pin_count())
|
|
|
|
|
return false;
|
2012-01-28 19:20:09 +01:00
|
|
|
|
|
|
|
|
bool rc = false;
|
2014-03-29 04:51:30 +01:00
|
|
|
unsigned word_base = vector_width() * widx;
|
2012-02-06 02:41:11 +01:00
|
|
|
for (unsigned idx = plsb ; idx <= pmsb ; idx += 1) {
|
2014-03-29 04:51:30 +01:00
|
|
|
if (lref_mask_[idx+word_base])
|
2012-01-28 19:20:09 +01:00
|
|
|
rc = true;
|
|
|
|
|
else
|
2014-03-29 04:51:30 +01:00
|
|
|
lref_mask_[idx+word_base] = true;
|
2012-01-28 19:20:09 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
|
2002-05-26 03:39:02 +02:00
|
|
|
void NetNet::incr_lref()
|
|
|
|
|
{
|
|
|
|
|
lref_count_ += 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void NetNet::decr_lref()
|
|
|
|
|
{
|
2023-04-13 22:00:34 +02:00
|
|
|
ivl_assert(*this, lref_count_ > 0);
|
2002-05-26 03:39:02 +02:00
|
|
|
lref_count_ -= 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned NetNet::get_refs() const
|
|
|
|
|
{
|
|
|
|
|
return lref_count_ + eref_count_;
|
|
|
|
|
}
|
|
|
|
|
|
2006-09-23 06:57:19 +02:00
|
|
|
void NetNet::add_delay_path(NetDelaySrc*path)
|
|
|
|
|
{
|
|
|
|
|
delay_paths_.push_back(path);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned NetNet::delay_paths(void)const
|
|
|
|
|
{
|
|
|
|
|
return delay_paths_.size();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const NetDelaySrc* NetNet::delay_path(unsigned idx) const
|
|
|
|
|
{
|
2023-04-13 22:00:34 +02:00
|
|
|
ivl_assert(*this, idx < delay_paths_.size());
|
2006-09-23 06:57:19 +02:00
|
|
|
return delay_paths_[idx];
|
|
|
|
|
}
|
2002-05-26 03:39:02 +02:00
|
|
|
|
2005-01-09 21:16:00 +01:00
|
|
|
NetPartSelect::NetPartSelect(NetNet*sig, unsigned off, unsigned wid,
|
2013-07-29 19:21:54 +02:00
|
|
|
NetPartSelect::dir_t dir__,
|
|
|
|
|
bool signed_flag__)
|
2004-12-11 03:31:25 +01:00
|
|
|
: NetNode(sig->scope(), sig->scope()->local_symbol(), 2),
|
2013-07-29 19:21:54 +02:00
|
|
|
off_(off), wid_(wid), dir_(dir__), signed_flag_(signed_flag__)
|
2004-12-11 03:31:25 +01:00
|
|
|
{
|
|
|
|
|
set_line(*sig);
|
|
|
|
|
|
2005-01-09 21:16:00 +01:00
|
|
|
switch (dir_) {
|
|
|
|
|
case NetPartSelect::VP:
|
|
|
|
|
pin(0).set_dir(Link::OUTPUT);
|
|
|
|
|
pin(1).set_dir(Link::INPUT);
|
|
|
|
|
break;
|
|
|
|
|
case NetPartSelect::PV:
|
|
|
|
|
pin(0).set_dir(Link::INPUT);
|
|
|
|
|
pin(1).set_dir(Link::OUTPUT);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2009-03-06 01:31:48 +01:00
|
|
|
|
|
|
|
|
connect(pin(1), sig->pin(0));
|
2004-12-11 03:31:25 +01:00
|
|
|
}
|
|
|
|
|
|
2005-05-09 01:40:14 +02:00
|
|
|
NetPartSelect::NetPartSelect(NetNet*sig, NetNet*sel,
|
2010-05-13 03:53:56 +02:00
|
|
|
unsigned wid, bool signed_flag__)
|
2005-05-09 01:40:14 +02:00
|
|
|
: NetNode(sig->scope(), sig->scope()->local_symbol(), 3),
|
2010-05-13 03:53:56 +02:00
|
|
|
off_(0), wid_(wid), dir_(VP), signed_flag_(signed_flag__)
|
2005-05-09 01:40:14 +02:00
|
|
|
{
|
|
|
|
|
switch (dir_) {
|
|
|
|
|
case NetPartSelect::VP:
|
|
|
|
|
pin(0).set_dir(Link::OUTPUT);
|
|
|
|
|
pin(1).set_dir(Link::INPUT);
|
|
|
|
|
break;
|
|
|
|
|
case NetPartSelect::PV:
|
2009-08-29 01:50:59 +02:00
|
|
|
/* Only a vector to part can be a variable select. */
|
2023-04-13 22:00:34 +02:00
|
|
|
ivl_assert(*this, 0);
|
2005-05-09 01:40:14 +02:00
|
|
|
}
|
|
|
|
|
pin(2).set_dir(Link::INPUT);
|
2009-03-06 01:31:48 +01:00
|
|
|
|
|
|
|
|
connect(pin(1), sig->pin(0));
|
|
|
|
|
connect(pin(2), sel->pin(0));
|
2005-05-09 01:40:14 +02:00
|
|
|
}
|
|
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
NetPartSelect::~NetPartSelect()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned NetPartSelect::width() const
|
|
|
|
|
{
|
|
|
|
|
return wid_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned NetPartSelect::base() const
|
|
|
|
|
{
|
|
|
|
|
return off_;
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-14 03:09:13 +02:00
|
|
|
NetSubstitute::NetSubstitute(NetNet*sig, NetNet*sub, unsigned wid, unsigned off)
|
|
|
|
|
: NetNode(sig->scope(), sig->scope()->local_symbol(), 3), wid_(wid), off_(off)
|
|
|
|
|
{
|
|
|
|
|
pin(0).set_dir(Link::OUTPUT);
|
|
|
|
|
pin(1).set_dir(Link::INPUT);
|
|
|
|
|
pin(2).set_dir(Link::INPUT);
|
|
|
|
|
connect(pin(1), sig->pin(0));
|
|
|
|
|
connect(pin(2), sub->pin(0));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NetSubstitute::~NetSubstitute()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
1999-09-29 20:36:02 +02:00
|
|
|
NetProc::NetProc()
|
|
|
|
|
: next_(0)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
1998-11-04 00:28:49 +01:00
|
|
|
NetProc::~NetProc()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2008-10-22 07:15:49 +02:00
|
|
|
NetProcTop::NetProcTop(NetScope*s, ivl_process_type_t t, NetProc*st)
|
2000-10-28 02:51:41 +02:00
|
|
|
: type_(t), statement_(st), scope_(s)
|
1999-07-18 07:52:46 +02:00
|
|
|
{
|
2016-02-21 00:52:00 +01:00
|
|
|
synthesized_design_ = 0;
|
1999-07-18 07:52:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NetProcTop::~NetProcTop()
|
|
|
|
|
{
|
2016-02-21 00:52:00 +01:00
|
|
|
if (!synthesized_design_) {
|
|
|
|
|
delete statement_;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NexusSet nex_set;
|
|
|
|
|
statement_->nex_output(nex_set);
|
|
|
|
|
|
1999-07-18 07:52:46 +02:00
|
|
|
delete statement_;
|
2016-02-21 00:52:00 +01:00
|
|
|
|
|
|
|
|
bool flag = false;
|
|
|
|
|
for (unsigned idx = 0 ; idx < nex_set.size() ; idx += 1) {
|
|
|
|
|
|
|
|
|
|
NetNet*net = nex_set[idx].lnk.nexus()->pick_any_net();
|
|
|
|
|
if (net->peek_lref() > 0) {
|
|
|
|
|
cerr << get_fileline() << ": warning: '" << net->name()
|
|
|
|
|
<< "' is driven by more than one process." << endl;
|
|
|
|
|
flag = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (flag) {
|
|
|
|
|
cerr << get_fileline() << ": sorry: Cannot synthesize signals "
|
|
|
|
|
"that are driven by more than one process." << endl;
|
|
|
|
|
synthesized_design_->errors += 1;
|
|
|
|
|
}
|
1999-07-18 07:52:46 +02:00
|
|
|
}
|
|
|
|
|
|
1999-07-18 23:17:50 +02:00
|
|
|
NetProc* NetProcTop::statement()
|
|
|
|
|
{
|
|
|
|
|
return statement_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const NetProc* NetProcTop::statement() const
|
|
|
|
|
{
|
|
|
|
|
return statement_;
|
|
|
|
|
}
|
|
|
|
|
|
2000-11-11 01:03:36 +01:00
|
|
|
NetScope* NetProcTop::scope()
|
|
|
|
|
{
|
|
|
|
|
return scope_;
|
|
|
|
|
}
|
|
|
|
|
|
2008-11-07 06:31:34 +01:00
|
|
|
const NetScope* NetProcTop::scope() const
|
|
|
|
|
{
|
|
|
|
|
return scope_;
|
|
|
|
|
}
|
|
|
|
|
|
2008-12-22 17:18:01 +01:00
|
|
|
NetAnalogTop::NetAnalogTop(NetScope*scope__, ivl_process_type_t t, NetProc*st)
|
|
|
|
|
: type_(t), statement_(st), scope_(scope__)
|
2008-10-22 07:15:49 +02:00
|
|
|
{
|
|
|
|
|
next_ = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NetAnalogTop::~NetAnalogTop()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2008-11-07 06:31:34 +01:00
|
|
|
NetProc* NetAnalogTop::statement()
|
|
|
|
|
{
|
|
|
|
|
return statement_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const NetProc* NetAnalogTop::statement() const
|
|
|
|
|
{
|
|
|
|
|
return statement_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NetScope* NetAnalogTop::scope()
|
|
|
|
|
{
|
|
|
|
|
return scope_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const NetScope* NetAnalogTop::scope() const
|
2000-10-28 02:51:41 +02:00
|
|
|
{
|
|
|
|
|
return scope_;
|
|
|
|
|
}
|
|
|
|
|
|
2010-10-16 19:53:20 +02:00
|
|
|
NetCastInt2::NetCastInt2(NetScope*scope__, perm_string n, unsigned width__)
|
|
|
|
|
: NetNode(scope__, n, 2), width_(width__)
|
|
|
|
|
{
|
|
|
|
|
pin(0).set_dir(Link::OUTPUT);
|
|
|
|
|
pin(1).set_dir(Link::INPUT);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NetCastInt4::NetCastInt4(NetScope*scope__, perm_string n, unsigned width__)
|
2008-10-06 18:53:39 +02:00
|
|
|
: NetNode(scope__, n, 2), width_(width__)
|
2008-06-21 03:11:11 +02:00
|
|
|
{
|
|
|
|
|
pin(0).set_dir(Link::OUTPUT);
|
|
|
|
|
pin(1).set_dir(Link::INPUT);
|
|
|
|
|
}
|
|
|
|
|
|
2008-10-06 18:53:39 +02:00
|
|
|
NetCastReal::NetCastReal(NetScope*scope__, perm_string n, bool signed_flag__)
|
|
|
|
|
: NetNode(scope__, n, 2), signed_flag_(signed_flag__)
|
2008-06-18 02:07:19 +02:00
|
|
|
{
|
|
|
|
|
pin(0).set_dir(Link::OUTPUT);
|
|
|
|
|
pin(1).set_dir(Link::INPUT);
|
|
|
|
|
}
|
|
|
|
|
|
2013-02-02 19:44:16 +01:00
|
|
|
NetConcat::NetConcat(NetScope*scope__, perm_string n, unsigned wid, unsigned cnt, bool trans_flag)
|
|
|
|
|
: NetNode(scope__, n, cnt+1), width_(wid), transparent_(trans_flag)
|
2004-12-30 00:55:43 +01:00
|
|
|
{
|
|
|
|
|
pin(0).set_dir(Link::OUTPUT);
|
|
|
|
|
for (unsigned idx = 1 ; idx < cnt+1 ; idx += 1) {
|
|
|
|
|
pin(idx).set_dir(Link::INPUT);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NetConcat::~NetConcat()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned NetConcat::width() const
|
|
|
|
|
{
|
|
|
|
|
return width_;
|
|
|
|
|
}
|
|
|
|
|
|
2008-10-06 18:53:39 +02:00
|
|
|
NetReplicate::NetReplicate(NetScope*scope__, perm_string n,
|
2005-02-08 01:12:36 +01:00
|
|
|
unsigned wid, unsigned rpt)
|
2008-10-06 18:53:39 +02:00
|
|
|
: NetNode(scope__, n, 2), width_(wid), repeat_(rpt)
|
2005-02-08 01:12:36 +01:00
|
|
|
{
|
|
|
|
|
pin(0).set_dir(Link::OUTPUT);
|
|
|
|
|
pin(1).set_dir(Link::INPUT);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NetReplicate::~NetReplicate()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned NetReplicate::width() const
|
|
|
|
|
{
|
|
|
|
|
return width_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned NetReplicate::repeat() const
|
|
|
|
|
{
|
|
|
|
|
return repeat_;
|
|
|
|
|
}
|
|
|
|
|
|
1999-09-03 06:28:38 +02:00
|
|
|
/*
|
1999-11-01 03:07:40 +01:00
|
|
|
* The NetFF class represents an LPM_FF device. The pinout is assigned
|
|
|
|
|
* like so:
|
|
|
|
|
* 0 -- Clock
|
|
|
|
|
* 1 -- Enable
|
2005-04-25 01:44:01 +02:00
|
|
|
* 2 -- Aset
|
|
|
|
|
* 3 -- Aclr
|
|
|
|
|
* 4 -- Sset
|
|
|
|
|
* 5 -- Sclr
|
|
|
|
|
* 6 -- Data
|
|
|
|
|
* 7 -- Q
|
1999-11-01 03:07:40 +01:00
|
|
|
* ...
|
|
|
|
|
*/
|
|
|
|
|
|
2015-06-13 16:56:12 +02:00
|
|
|
NetFF::NetFF(NetScope*s, perm_string n, bool negedge__, unsigned width__)
|
|
|
|
|
: NetNode(s, n, 8), negedge_(negedge__), width_(width__)
|
1999-11-01 03:07:40 +01:00
|
|
|
{
|
|
|
|
|
pin_Clock().set_dir(Link::INPUT);
|
|
|
|
|
pin_Enable().set_dir(Link::INPUT);
|
|
|
|
|
pin_Aset().set_dir(Link::INPUT);
|
|
|
|
|
pin_Aclr().set_dir(Link::INPUT);
|
|
|
|
|
pin_Sset().set_dir(Link::INPUT);
|
|
|
|
|
pin_Sclr().set_dir(Link::INPUT);
|
2005-04-25 01:44:01 +02:00
|
|
|
pin_Data().set_dir(Link::INPUT);
|
|
|
|
|
pin_Q().set_dir(Link::OUTPUT);
|
1999-11-01 03:07:40 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NetFF::~NetFF()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-13 16:56:12 +02:00
|
|
|
bool NetFF::is_negedge() const
|
|
|
|
|
{
|
|
|
|
|
return negedge_;
|
|
|
|
|
}
|
|
|
|
|
|
1999-11-01 03:07:40 +01:00
|
|
|
unsigned NetFF::width() const
|
|
|
|
|
{
|
2005-04-25 01:44:01 +02:00
|
|
|
return width_;
|
1999-11-01 03:07:40 +01:00
|
|
|
}
|
|
|
|
|
|
2000-05-07 06:37:55 +02:00
|
|
|
Link& NetFF::pin_Clock()
|
1999-11-01 03:07:40 +01:00
|
|
|
{
|
|
|
|
|
return pin(0);
|
|
|
|
|
}
|
|
|
|
|
|
2000-05-07 06:37:55 +02:00
|
|
|
const Link& NetFF::pin_Clock() const
|
1999-11-02 05:55:34 +01:00
|
|
|
{
|
|
|
|
|
return pin(0);
|
|
|
|
|
}
|
|
|
|
|
|
2000-05-07 06:37:55 +02:00
|
|
|
Link& NetFF::pin_Enable()
|
1999-11-01 03:07:40 +01:00
|
|
|
{
|
|
|
|
|
return pin(1);
|
|
|
|
|
}
|
|
|
|
|
|
2000-05-07 06:37:55 +02:00
|
|
|
const Link& NetFF::pin_Enable() const
|
1999-11-02 05:55:34 +01:00
|
|
|
{
|
|
|
|
|
return pin(1);
|
|
|
|
|
}
|
|
|
|
|
|
2000-05-07 06:37:55 +02:00
|
|
|
Link& NetFF::pin_Aset()
|
1999-11-01 03:07:40 +01:00
|
|
|
{
|
2005-04-25 01:44:01 +02:00
|
|
|
return pin(2);
|
1999-11-01 03:07:40 +01:00
|
|
|
}
|
|
|
|
|
|
2002-09-26 05:18:04 +02:00
|
|
|
const Link& NetFF::pin_Aset() const
|
|
|
|
|
{
|
2005-04-25 01:44:01 +02:00
|
|
|
return pin(2);
|
2002-09-26 05:18:04 +02:00
|
|
|
}
|
|
|
|
|
|
2000-05-07 06:37:55 +02:00
|
|
|
Link& NetFF::pin_Aclr()
|
1999-11-01 03:07:40 +01:00
|
|
|
{
|
2005-04-25 01:44:01 +02:00
|
|
|
return pin(3);
|
1999-11-01 03:07:40 +01:00
|
|
|
}
|
|
|
|
|
|
2002-09-26 05:18:04 +02:00
|
|
|
const Link& NetFF::pin_Aclr() const
|
|
|
|
|
{
|
2005-04-25 01:44:01 +02:00
|
|
|
return pin(3);
|
1999-11-01 03:07:40 +01:00
|
|
|
}
|
|
|
|
|
|
2000-05-07 06:37:55 +02:00
|
|
|
Link& NetFF::pin_Sset()
|
1999-11-01 03:07:40 +01:00
|
|
|
{
|
2005-04-25 01:44:01 +02:00
|
|
|
return pin(4);
|
1999-11-01 03:07:40 +01:00
|
|
|
}
|
|
|
|
|
|
2003-09-04 01:32:10 +02:00
|
|
|
const Link& NetFF::pin_Sset() const
|
|
|
|
|
{
|
2005-04-25 01:44:01 +02:00
|
|
|
return pin(4);
|
2003-09-04 01:32:10 +02:00
|
|
|
}
|
|
|
|
|
|
2000-05-07 06:37:55 +02:00
|
|
|
Link& NetFF::pin_Sclr()
|
1999-11-01 03:07:40 +01:00
|
|
|
{
|
2005-04-25 01:44:01 +02:00
|
|
|
return pin(5);
|
1999-11-01 03:07:40 +01:00
|
|
|
}
|
|
|
|
|
|
2003-08-15 04:23:52 +02:00
|
|
|
const Link& NetFF::pin_Sclr() const
|
|
|
|
|
{
|
2005-04-25 01:44:01 +02:00
|
|
|
return pin(5);
|
2003-08-15 04:23:52 +02:00
|
|
|
}
|
|
|
|
|
|
2005-04-25 01:44:01 +02:00
|
|
|
Link& NetFF::pin_Data()
|
1999-11-01 03:07:40 +01:00
|
|
|
{
|
2005-04-25 01:44:01 +02:00
|
|
|
return pin(6);
|
1999-11-01 03:07:40 +01:00
|
|
|
}
|
|
|
|
|
|
2005-04-25 01:44:01 +02:00
|
|
|
const Link& NetFF::pin_Data() const
|
1999-11-02 05:55:34 +01:00
|
|
|
{
|
2005-04-25 01:44:01 +02:00
|
|
|
return pin(6);
|
1999-11-02 05:55:34 +01:00
|
|
|
}
|
|
|
|
|
|
2005-04-25 01:44:01 +02:00
|
|
|
Link& NetFF::pin_Q()
|
1999-11-01 03:07:40 +01:00
|
|
|
{
|
2005-04-25 01:44:01 +02:00
|
|
|
return pin(7);
|
1999-11-01 03:07:40 +01:00
|
|
|
}
|
|
|
|
|
|
2005-04-25 01:44:01 +02:00
|
|
|
const Link& NetFF::pin_Q() const
|
1999-11-01 03:07:40 +01:00
|
|
|
{
|
2005-04-25 01:44:01 +02:00
|
|
|
return pin(7);
|
1999-11-01 03:07:40 +01:00
|
|
|
}
|
|
|
|
|
|
2002-10-23 03:45:24 +02:00
|
|
|
void NetFF::aset_value(const verinum&val)
|
|
|
|
|
{
|
|
|
|
|
aset_value_ = val;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const verinum& NetFF::aset_value() const
|
|
|
|
|
{
|
|
|
|
|
return aset_value_;
|
|
|
|
|
}
|
|
|
|
|
|
2003-08-15 04:23:52 +02:00
|
|
|
void NetFF::sset_value(const verinum&val)
|
|
|
|
|
{
|
|
|
|
|
sset_value_ = val;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const verinum& NetFF::sset_value() const
|
|
|
|
|
{
|
|
|
|
|
return sset_value_;
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-10 14:37:25 +01:00
|
|
|
/*
|
|
|
|
|
* The NetLatch class represents an LPM_LATCH device. The pinout is assigned
|
|
|
|
|
* like so:
|
|
|
|
|
* 0 -- Enable
|
|
|
|
|
* 1 -- Data
|
|
|
|
|
* 2 -- Q
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
NetLatch::NetLatch(NetScope*s, perm_string n, unsigned width__)
|
|
|
|
|
: NetNode(s, n, 3), width_(width__)
|
|
|
|
|
{
|
|
|
|
|
pin_Enable().set_dir(Link::INPUT);
|
|
|
|
|
pin_Data().set_dir(Link::INPUT);
|
|
|
|
|
pin_Q().set_dir(Link::OUTPUT);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NetLatch::~NetLatch()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned NetLatch::width() const
|
|
|
|
|
{
|
|
|
|
|
return width_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Link& NetLatch::pin_Enable()
|
|
|
|
|
{
|
|
|
|
|
return pin(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const Link& NetLatch::pin_Enable() const
|
|
|
|
|
{
|
|
|
|
|
return pin(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Link& NetLatch::pin_Data()
|
|
|
|
|
{
|
|
|
|
|
return pin(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const Link& NetLatch::pin_Data() const
|
|
|
|
|
{
|
|
|
|
|
return pin(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Link& NetLatch::pin_Q()
|
|
|
|
|
{
|
|
|
|
|
return pin(2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const Link& NetLatch::pin_Q() const
|
|
|
|
|
{
|
|
|
|
|
return pin(2);
|
|
|
|
|
}
|
1999-11-01 03:07:40 +01:00
|
|
|
|
2008-05-06 07:00:39 +02:00
|
|
|
NetAbs::NetAbs(NetScope*s, perm_string n, unsigned w)
|
|
|
|
|
: NetNode(s, n, 2), width_(w)
|
|
|
|
|
{
|
|
|
|
|
pin(0).set_dir(Link::OUTPUT);
|
|
|
|
|
pin(1).set_dir(Link::INPUT);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NetAbs::~NetAbs()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned NetAbs::width() const
|
|
|
|
|
{
|
|
|
|
|
return width_;
|
|
|
|
|
}
|
|
|
|
|
|
1999-11-01 03:07:40 +01:00
|
|
|
/*
|
|
|
|
|
* The NetAddSub class represents an LPM_ADD_SUB device. The pinout is
|
1999-09-03 06:28:38 +02:00
|
|
|
* assigned like so:
|
2008-09-14 03:28:43 +02:00
|
|
|
* 0 -- Cout
|
|
|
|
|
* 1 -- DataA (normally a vector)
|
|
|
|
|
* 2 -- DataB (normally a vector)
|
|
|
|
|
* 3 -- Result (normally a vector)
|
1999-09-03 06:28:38 +02:00
|
|
|
*/
|
2004-02-18 18:11:54 +01:00
|
|
|
NetAddSub::NetAddSub(NetScope*s, perm_string n, unsigned w)
|
2008-09-14 03:28:43 +02:00
|
|
|
: NetNode(s, n, 4), width_(w)
|
2004-02-18 18:11:54 +01:00
|
|
|
{
|
2008-09-14 03:28:43 +02:00
|
|
|
pin(0).set_dir(Link::OUTPUT); // Cout
|
|
|
|
|
pin(1).set_dir(Link::INPUT); // DataA
|
|
|
|
|
pin(2).set_dir(Link::INPUT); // DataB
|
|
|
|
|
pin(3).set_dir(Link::OUTPUT); // Result
|
1999-09-03 06:28:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NetAddSub::~NetAddSub()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
1999-09-04 03:57:15 +02:00
|
|
|
unsigned NetAddSub::width()const
|
|
|
|
|
{
|
2004-12-11 03:31:25 +01:00
|
|
|
return width_;
|
1999-09-04 03:57:15 +02:00
|
|
|
}
|
|
|
|
|
|
2000-05-07 06:37:55 +02:00
|
|
|
Link& NetAddSub::pin_Cout()
|
1999-12-16 03:42:14 +01:00
|
|
|
{
|
2008-09-14 03:28:43 +02:00
|
|
|
return pin(0);
|
1999-12-16 03:42:14 +01:00
|
|
|
}
|
|
|
|
|
|
2000-05-07 06:37:55 +02:00
|
|
|
const Link& NetAddSub::pin_Cout() const
|
1999-12-16 03:42:14 +01:00
|
|
|
{
|
2008-09-14 03:28:43 +02:00
|
|
|
return pin(0);
|
1999-12-16 03:42:14 +01:00
|
|
|
}
|
|
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
Link& NetAddSub::pin_DataA()
|
1999-09-03 06:28:38 +02:00
|
|
|
{
|
2008-09-14 03:28:43 +02:00
|
|
|
return pin(1);
|
1999-09-03 06:28:38 +02:00
|
|
|
}
|
|
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
const Link& NetAddSub::pin_DataA() const
|
1999-11-05 05:40:40 +01:00
|
|
|
{
|
2008-09-14 03:28:43 +02:00
|
|
|
return pin(1);
|
1999-11-05 05:40:40 +01:00
|
|
|
}
|
|
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
Link& NetAddSub::pin_DataB()
|
1999-09-03 06:28:38 +02:00
|
|
|
{
|
2008-09-14 03:28:43 +02:00
|
|
|
return pin(2);
|
1999-09-03 06:28:38 +02:00
|
|
|
}
|
|
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
const Link& NetAddSub::pin_DataB() const
|
1999-11-05 05:40:40 +01:00
|
|
|
{
|
2008-09-14 03:28:43 +02:00
|
|
|
return pin(2);
|
1999-11-05 05:40:40 +01:00
|
|
|
}
|
|
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
Link& NetAddSub::pin_Result()
|
1999-09-03 06:28:38 +02:00
|
|
|
{
|
2008-09-14 03:28:43 +02:00
|
|
|
return pin(3);
|
1999-09-03 06:28:38 +02:00
|
|
|
}
|
|
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
const Link& NetAddSub::pin_Result() const
|
1999-10-31 05:11:27 +01:00
|
|
|
{
|
2008-09-14 03:28:43 +02:00
|
|
|
return pin(3);
|
1999-10-31 05:11:27 +01:00
|
|
|
}
|
|
|
|
|
|
2008-10-06 18:53:39 +02:00
|
|
|
NetArrayDq::NetArrayDq(NetScope*s, perm_string n, NetNet*mem__, unsigned awid)
|
2007-01-16 06:44:14 +01:00
|
|
|
: NetNode(s, n, 2),
|
2008-10-06 18:53:39 +02:00
|
|
|
mem_(mem__), awidth_(awid)
|
2007-01-16 06:44:14 +01:00
|
|
|
{
|
2008-09-11 04:34:28 +02:00
|
|
|
pin(0).set_dir(Link::OUTPUT); // Result
|
|
|
|
|
pin(1).set_dir(Link::INPUT); // Address
|
2008-01-16 04:39:53 +01:00
|
|
|
// Increment the expression reference count for the target
|
|
|
|
|
// memory so that it is not deleted underneath me.
|
2008-10-06 18:53:39 +02:00
|
|
|
mem_->incr_eref();
|
2007-01-16 06:44:14 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NetArrayDq::~NetArrayDq()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned NetArrayDq::width() const
|
|
|
|
|
{
|
|
|
|
|
return mem_->vector_width();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned NetArrayDq::awidth() const
|
|
|
|
|
{
|
|
|
|
|
return awidth_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const NetNet* NetArrayDq::mem() const
|
|
|
|
|
{
|
|
|
|
|
return mem_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Link& NetArrayDq::pin_Result()
|
|
|
|
|
{
|
|
|
|
|
return pin(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Link& NetArrayDq::pin_Address()
|
|
|
|
|
{
|
|
|
|
|
return pin(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const Link& NetArrayDq::pin_Result() const
|
|
|
|
|
{
|
|
|
|
|
return pin(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const Link& NetArrayDq::pin_Address() const
|
|
|
|
|
{
|
|
|
|
|
return pin(1);
|
|
|
|
|
}
|
|
|
|
|
|
1999-11-14 21:24:28 +01:00
|
|
|
/*
|
|
|
|
|
* The pinout for the NetCLShift is:
|
2005-02-19 03:43:38 +01:00
|
|
|
* 0 -- Result
|
|
|
|
|
* 1 -- Data
|
|
|
|
|
* 2 -- Distance
|
1999-11-14 21:24:28 +01:00
|
|
|
*/
|
2004-02-18 18:11:54 +01:00
|
|
|
NetCLShift::NetCLShift(NetScope*s, perm_string n,
|
2008-10-06 18:53:39 +02:00
|
|
|
unsigned width__, unsigned width_dist__,
|
|
|
|
|
bool right_flag__, bool signed_flag__)
|
2005-02-19 03:43:38 +01:00
|
|
|
: NetNode(s, n, 3),
|
2008-10-06 18:53:39 +02:00
|
|
|
width_(width__), width_dist_(width_dist__),
|
|
|
|
|
right_flag_(right_flag__), signed_flag_(signed_flag__)
|
1999-11-14 21:24:28 +01:00
|
|
|
{
|
2008-09-11 04:34:28 +02:00
|
|
|
pin(0).set_dir(Link::OUTPUT); // Result
|
|
|
|
|
pin(1).set_dir(Link::INPUT); // Data
|
|
|
|
|
pin(2).set_dir(Link::INPUT); // Distance
|
1999-11-14 21:24:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NetCLShift::~NetCLShift()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned NetCLShift::width() const
|
|
|
|
|
{
|
|
|
|
|
return width_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned NetCLShift::width_dist() const
|
|
|
|
|
{
|
|
|
|
|
return width_dist_;
|
|
|
|
|
}
|
|
|
|
|
|
2004-06-30 04:16:26 +02:00
|
|
|
bool NetCLShift::right_flag() const
|
|
|
|
|
{
|
|
|
|
|
return right_flag_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool NetCLShift::signed_flag() const
|
|
|
|
|
{
|
|
|
|
|
return signed_flag_;
|
|
|
|
|
}
|
|
|
|
|
|
2005-02-19 03:43:38 +01:00
|
|
|
Link& NetCLShift::pin_Data()
|
1999-11-14 21:24:28 +01:00
|
|
|
{
|
|
|
|
|
return pin(1);
|
|
|
|
|
}
|
|
|
|
|
|
2005-02-19 03:43:38 +01:00
|
|
|
const Link& NetCLShift::pin_Data() const
|
1999-11-14 21:24:28 +01:00
|
|
|
{
|
|
|
|
|
return pin(1);
|
|
|
|
|
}
|
|
|
|
|
|
2005-02-19 03:43:38 +01:00
|
|
|
Link& NetCLShift::pin_Result()
|
1999-11-14 21:24:28 +01:00
|
|
|
{
|
2005-02-19 03:43:38 +01:00
|
|
|
return pin(0);
|
1999-11-14 21:24:28 +01:00
|
|
|
}
|
|
|
|
|
|
2005-02-19 03:43:38 +01:00
|
|
|
const Link& NetCLShift::pin_Result() const
|
1999-11-14 21:24:28 +01:00
|
|
|
{
|
2005-02-19 03:43:38 +01:00
|
|
|
return pin(0);
|
1999-11-14 21:24:28 +01:00
|
|
|
}
|
|
|
|
|
|
2005-02-19 03:43:38 +01:00
|
|
|
Link& NetCLShift::pin_Distance()
|
1999-11-14 21:24:28 +01:00
|
|
|
{
|
2005-02-19 03:43:38 +01:00
|
|
|
return pin(2);
|
1999-11-14 21:24:28 +01:00
|
|
|
}
|
|
|
|
|
|
2005-02-19 03:43:38 +01:00
|
|
|
const Link& NetCLShift::pin_Distance() const
|
1999-11-14 21:24:28 +01:00
|
|
|
{
|
2005-02-19 03:43:38 +01:00
|
|
|
return pin(2);
|
1999-11-14 21:24:28 +01:00
|
|
|
}
|
|
|
|
|
|
2004-02-18 18:11:54 +01:00
|
|
|
NetCompare::NetCompare(NetScope*s, perm_string n, unsigned wi)
|
2008-10-14 04:43:02 +02:00
|
|
|
: NetNode(s, n, 8), width_(wi)
|
1999-11-15 00:43:45 +01:00
|
|
|
{
|
2003-04-11 07:18:08 +02:00
|
|
|
signed_flag_ = false;
|
2008-10-14 04:43:02 +02:00
|
|
|
pin(0).set_dir(Link::OUTPUT); // AGB
|
|
|
|
|
pin(1).set_dir(Link::OUTPUT); // AGEB
|
|
|
|
|
pin(2).set_dir(Link::OUTPUT); // AEB
|
|
|
|
|
pin(3).set_dir(Link::OUTPUT); // ANEB
|
|
|
|
|
pin(4).set_dir(Link::OUTPUT); // ALB
|
|
|
|
|
pin(5).set_dir(Link::OUTPUT); // ALEB
|
|
|
|
|
pin(6).set_dir(Link::INPUT); // DataA
|
|
|
|
|
pin(7).set_dir(Link::INPUT); // DataB
|
1999-11-15 00:43:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NetCompare::~NetCompare()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned NetCompare::width() const
|
|
|
|
|
{
|
|
|
|
|
return width_;
|
|
|
|
|
}
|
|
|
|
|
|
2003-04-11 07:18:08 +02:00
|
|
|
bool NetCompare::get_signed() const
|
|
|
|
|
{
|
|
|
|
|
return signed_flag_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void NetCompare::set_signed(bool flag)
|
|
|
|
|
{
|
|
|
|
|
signed_flag_ = flag;
|
|
|
|
|
}
|
|
|
|
|
|
2008-09-14 03:28:43 +02:00
|
|
|
|
2000-05-07 06:37:55 +02:00
|
|
|
Link& NetCompare::pin_AGB()
|
1999-11-15 00:43:45 +01:00
|
|
|
{
|
2008-10-14 04:43:02 +02:00
|
|
|
return pin(0);
|
1999-11-15 00:43:45 +01:00
|
|
|
}
|
|
|
|
|
|
2000-05-07 06:37:55 +02:00
|
|
|
const Link& NetCompare::pin_AGB() const
|
1999-11-15 00:43:45 +01:00
|
|
|
{
|
2008-10-14 04:43:02 +02:00
|
|
|
return pin(0);
|
1999-11-15 00:43:45 +01:00
|
|
|
}
|
|
|
|
|
|
2000-05-07 06:37:55 +02:00
|
|
|
Link& NetCompare::pin_AGEB()
|
1999-11-15 00:43:45 +01:00
|
|
|
{
|
2008-10-14 04:43:02 +02:00
|
|
|
return pin(1);
|
1999-11-15 00:43:45 +01:00
|
|
|
}
|
|
|
|
|
|
2000-05-07 06:37:55 +02:00
|
|
|
const Link& NetCompare::pin_AGEB() const
|
1999-11-15 00:43:45 +01:00
|
|
|
{
|
2008-10-14 04:43:02 +02:00
|
|
|
return pin(1);
|
1999-11-15 00:43:45 +01:00
|
|
|
}
|
|
|
|
|
|
2000-05-07 06:37:55 +02:00
|
|
|
Link& NetCompare::pin_AEB()
|
1999-11-15 00:43:45 +01:00
|
|
|
{
|
2008-10-14 04:43:02 +02:00
|
|
|
return pin(2);
|
1999-11-15 00:43:45 +01:00
|
|
|
}
|
|
|
|
|
|
2000-05-07 06:37:55 +02:00
|
|
|
const Link& NetCompare::pin_AEB() const
|
1999-11-15 00:43:45 +01:00
|
|
|
{
|
2008-10-14 04:43:02 +02:00
|
|
|
return pin(2);
|
1999-11-15 00:43:45 +01:00
|
|
|
}
|
|
|
|
|
|
2000-05-07 06:37:55 +02:00
|
|
|
Link& NetCompare::pin_ANEB()
|
1999-11-15 00:43:45 +01:00
|
|
|
{
|
2008-10-14 04:43:02 +02:00
|
|
|
return pin(3);
|
1999-11-15 00:43:45 +01:00
|
|
|
}
|
|
|
|
|
|
2000-05-07 06:37:55 +02:00
|
|
|
const Link& NetCompare::pin_ANEB() const
|
1999-11-15 00:43:45 +01:00
|
|
|
{
|
2008-10-14 04:43:02 +02:00
|
|
|
return pin(3);
|
1999-11-15 00:43:45 +01:00
|
|
|
}
|
|
|
|
|
|
2000-05-07 06:37:55 +02:00
|
|
|
Link& NetCompare::pin_ALB()
|
1999-11-15 00:43:45 +01:00
|
|
|
{
|
2008-10-14 04:43:02 +02:00
|
|
|
return pin(4);
|
1999-11-15 00:43:45 +01:00
|
|
|
}
|
|
|
|
|
|
2000-05-07 06:37:55 +02:00
|
|
|
const Link& NetCompare::pin_ALB() const
|
1999-11-15 00:43:45 +01:00
|
|
|
{
|
2008-10-14 04:43:02 +02:00
|
|
|
return pin(4);
|
1999-11-15 00:43:45 +01:00
|
|
|
}
|
|
|
|
|
|
2000-05-07 06:37:55 +02:00
|
|
|
Link& NetCompare::pin_ALEB()
|
1999-11-15 00:43:45 +01:00
|
|
|
{
|
2008-10-14 04:43:02 +02:00
|
|
|
return pin(5);
|
1999-11-15 00:43:45 +01:00
|
|
|
}
|
|
|
|
|
|
2000-05-07 06:37:55 +02:00
|
|
|
const Link& NetCompare::pin_ALEB() const
|
1999-11-15 00:43:45 +01:00
|
|
|
{
|
2008-10-14 04:43:02 +02:00
|
|
|
return pin(5);
|
1999-11-15 00:43:45 +01:00
|
|
|
}
|
|
|
|
|
|
2005-01-16 05:20:32 +01:00
|
|
|
Link& NetCompare::pin_DataA()
|
1999-11-15 00:43:45 +01:00
|
|
|
{
|
2008-10-14 04:43:02 +02:00
|
|
|
return pin(6);
|
1999-11-15 00:43:45 +01:00
|
|
|
}
|
|
|
|
|
|
2005-01-16 05:20:32 +01:00
|
|
|
const Link& NetCompare::pin_DataA() const
|
1999-11-15 00:43:45 +01:00
|
|
|
{
|
2008-10-14 04:43:02 +02:00
|
|
|
return pin(6);
|
1999-11-15 00:43:45 +01:00
|
|
|
}
|
|
|
|
|
|
2005-01-16 05:20:32 +01:00
|
|
|
Link& NetCompare::pin_DataB()
|
1999-11-15 00:43:45 +01:00
|
|
|
{
|
2008-10-14 04:43:02 +02:00
|
|
|
return pin(7);
|
1999-11-15 00:43:45 +01:00
|
|
|
}
|
|
|
|
|
|
2005-01-16 05:20:32 +01:00
|
|
|
const Link& NetCompare::pin_DataB() const
|
1999-11-15 00:43:45 +01:00
|
|
|
{
|
2008-10-14 04:43:02 +02:00
|
|
|
return pin(7);
|
1999-11-15 00:43:45 +01:00
|
|
|
}
|
|
|
|
|
|
2004-02-18 18:11:54 +01:00
|
|
|
NetDivide::NetDivide(NetScope*sc, perm_string n, unsigned wr,
|
2000-04-01 23:40:22 +02:00
|
|
|
unsigned wa, unsigned wb)
|
2005-02-19 03:43:38 +01:00
|
|
|
: NetNode(sc, n, 3),
|
2004-06-30 04:16:26 +02:00
|
|
|
width_r_(wr), width_a_(wa), width_b_(wb), signed_flag_(false)
|
2000-04-01 23:40:22 +02:00
|
|
|
{
|
2008-09-11 04:34:28 +02:00
|
|
|
pin(0).set_dir(Link::OUTPUT); // Result
|
|
|
|
|
pin(1).set_dir(Link::INPUT); // DataA
|
|
|
|
|
pin(2).set_dir(Link::INPUT); // DataB
|
2000-04-01 23:40:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NetDivide::~NetDivide()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned NetDivide::width_r() const
|
|
|
|
|
{
|
|
|
|
|
return width_r_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned NetDivide::width_a() const
|
|
|
|
|
{
|
|
|
|
|
return width_a_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned NetDivide::width_b() const
|
|
|
|
|
{
|
|
|
|
|
return width_b_;
|
|
|
|
|
}
|
|
|
|
|
|
2004-06-30 04:16:26 +02:00
|
|
|
void NetDivide::set_signed(bool flag)
|
|
|
|
|
{
|
|
|
|
|
signed_flag_ = flag;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool NetDivide::get_signed() const
|
|
|
|
|
{
|
|
|
|
|
return signed_flag_;
|
|
|
|
|
}
|
|
|
|
|
|
2005-02-19 03:43:38 +01:00
|
|
|
Link& NetDivide::pin_Result()
|
2000-04-01 23:40:22 +02:00
|
|
|
{
|
2005-02-19 03:43:38 +01:00
|
|
|
return pin(0);
|
2000-04-01 23:40:22 +02:00
|
|
|
}
|
|
|
|
|
|
2005-02-19 03:43:38 +01:00
|
|
|
const Link& NetDivide::pin_Result() const
|
2000-04-01 23:40:22 +02:00
|
|
|
{
|
2005-02-19 03:43:38 +01:00
|
|
|
return pin(0);
|
2000-04-01 23:40:22 +02:00
|
|
|
}
|
|
|
|
|
|
2005-02-19 03:43:38 +01:00
|
|
|
Link& NetDivide::pin_DataA()
|
2000-04-01 23:40:22 +02:00
|
|
|
{
|
2005-02-19 03:43:38 +01:00
|
|
|
return pin(1);
|
2000-04-01 23:40:22 +02:00
|
|
|
}
|
|
|
|
|
|
2005-02-19 03:43:38 +01:00
|
|
|
const Link& NetDivide::pin_DataA() const
|
2000-04-01 23:40:22 +02:00
|
|
|
{
|
2005-02-19 03:43:38 +01:00
|
|
|
return pin(1);
|
2000-04-01 23:40:22 +02:00
|
|
|
}
|
|
|
|
|
|
2005-02-19 03:43:38 +01:00
|
|
|
Link& NetDivide::pin_DataB()
|
2000-04-01 23:40:22 +02:00
|
|
|
{
|
2005-02-19 03:43:38 +01:00
|
|
|
return pin(2);
|
2000-04-01 23:40:22 +02:00
|
|
|
}
|
|
|
|
|
|
2005-02-19 03:43:38 +01:00
|
|
|
const Link& NetDivide::pin_DataB() const
|
2000-04-01 23:40:22 +02:00
|
|
|
{
|
2005-02-19 03:43:38 +01:00
|
|
|
return pin(2);
|
2000-04-01 23:40:22 +02:00
|
|
|
}
|
|
|
|
|
|
2005-07-07 18:22:49 +02:00
|
|
|
NetLiteral::NetLiteral(NetScope*sc, perm_string n, const verireal&val)
|
|
|
|
|
: NetNode(sc, n, 1), real_(val)
|
|
|
|
|
{
|
|
|
|
|
pin(0).set_dir(Link::OUTPUT);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NetLiteral::~NetLiteral()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-20 04:13:50 +02:00
|
|
|
ivl_variable_type_t NetLiteral::data_type() const
|
|
|
|
|
{
|
|
|
|
|
return IVL_VT_REAL;
|
|
|
|
|
}
|
|
|
|
|
|
2005-07-07 18:22:49 +02:00
|
|
|
const verireal& NetLiteral::value_real() const
|
|
|
|
|
{
|
|
|
|
|
return real_;
|
|
|
|
|
}
|
|
|
|
|
|
2004-02-18 18:11:54 +01:00
|
|
|
NetMult::NetMult(NetScope*sc, perm_string n, unsigned wr,
|
2005-01-28 06:39:33 +01:00
|
|
|
unsigned wa, unsigned wb)
|
|
|
|
|
: NetNode(sc, n, 3),
|
|
|
|
|
signed_(false), width_r_(wr), width_a_(wa), width_b_(wb)
|
2000-01-13 04:35:35 +01:00
|
|
|
{
|
2008-09-11 04:34:28 +02:00
|
|
|
pin(0).set_dir(Link::OUTPUT); // Result
|
|
|
|
|
pin(1).set_dir(Link::INPUT); // DataA
|
|
|
|
|
pin(2).set_dir(Link::INPUT); // DataB
|
2000-01-13 04:35:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NetMult::~NetMult()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2003-03-29 06:51:25 +01:00
|
|
|
void NetMult::set_signed(bool flag)
|
|
|
|
|
{
|
|
|
|
|
signed_ = flag;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool NetMult::get_signed() const
|
|
|
|
|
{
|
|
|
|
|
return signed_;
|
|
|
|
|
}
|
|
|
|
|
|
2000-01-13 04:35:35 +01:00
|
|
|
unsigned NetMult::width_r() const
|
|
|
|
|
{
|
|
|
|
|
return width_r_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned NetMult::width_a() const
|
|
|
|
|
{
|
|
|
|
|
return width_a_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned NetMult::width_b() const
|
|
|
|
|
{
|
|
|
|
|
return width_b_;
|
|
|
|
|
}
|
|
|
|
|
|
2005-01-28 06:39:33 +01:00
|
|
|
Link& NetMult::pin_Result()
|
2000-01-13 04:35:35 +01:00
|
|
|
{
|
|
|
|
|
return pin(0);
|
|
|
|
|
}
|
|
|
|
|
|
2005-01-28 06:39:33 +01:00
|
|
|
const Link& NetMult::pin_Result() const
|
2000-01-13 04:35:35 +01:00
|
|
|
{
|
|
|
|
|
return pin(0);
|
|
|
|
|
}
|
|
|
|
|
|
2005-01-28 06:39:33 +01:00
|
|
|
Link& NetMult::pin_DataA()
|
2000-01-13 04:35:35 +01:00
|
|
|
{
|
|
|
|
|
return pin(1);
|
|
|
|
|
}
|
|
|
|
|
|
2005-01-28 06:39:33 +01:00
|
|
|
const Link& NetMult::pin_DataA() const
|
2000-01-13 04:35:35 +01:00
|
|
|
{
|
|
|
|
|
return pin(1);
|
|
|
|
|
}
|
|
|
|
|
|
2005-01-28 06:39:33 +01:00
|
|
|
Link& NetMult::pin_DataB()
|
2000-01-13 04:35:35 +01:00
|
|
|
{
|
2005-01-28 06:39:33 +01:00
|
|
|
return pin(2);
|
2000-01-13 04:35:35 +01:00
|
|
|
}
|
|
|
|
|
|
2005-01-28 06:39:33 +01:00
|
|
|
const Link& NetMult::pin_DataB() const
|
2000-01-13 04:35:35 +01:00
|
|
|
{
|
2005-01-28 06:39:33 +01:00
|
|
|
return pin(2);
|
2000-01-13 04:35:35 +01:00
|
|
|
}
|
|
|
|
|
|
2008-01-31 02:53:06 +01:00
|
|
|
NetPow::NetPow(NetScope*sc, perm_string n, unsigned wr,
|
|
|
|
|
unsigned wa, unsigned wb)
|
|
|
|
|
: NetNode(sc, n, 3),
|
|
|
|
|
signed_(false), width_r_(wr), width_a_(wa), width_b_(wb)
|
|
|
|
|
{
|
2008-09-11 04:34:28 +02:00
|
|
|
pin(0).set_dir(Link::OUTPUT); // Result
|
|
|
|
|
pin(1).set_dir(Link::INPUT); // DataA
|
|
|
|
|
pin(2).set_dir(Link::INPUT); // DataB
|
2008-01-31 02:53:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NetPow::~NetPow()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void NetPow::set_signed(bool flag)
|
|
|
|
|
{
|
|
|
|
|
signed_ = flag;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool NetPow::get_signed() const
|
|
|
|
|
{
|
|
|
|
|
return signed_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned NetPow::width_r() const
|
|
|
|
|
{
|
|
|
|
|
return width_r_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned NetPow::width_a() const
|
|
|
|
|
{
|
|
|
|
|
return width_a_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned NetPow::width_b() const
|
|
|
|
|
{
|
|
|
|
|
return width_b_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Link& NetPow::pin_Result()
|
|
|
|
|
{
|
|
|
|
|
return pin(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const Link& NetPow::pin_Result() const
|
|
|
|
|
{
|
|
|
|
|
return pin(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Link& NetPow::pin_DataA()
|
|
|
|
|
{
|
|
|
|
|
return pin(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const Link& NetPow::pin_DataA() const
|
|
|
|
|
{
|
|
|
|
|
return pin(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Link& NetPow::pin_DataB()
|
|
|
|
|
{
|
|
|
|
|
return pin(2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const Link& NetPow::pin_DataB() const
|
|
|
|
|
{
|
|
|
|
|
return pin(2);
|
|
|
|
|
}
|
|
|
|
|
|
1999-11-04 04:53:26 +01:00
|
|
|
/*
|
|
|
|
|
* The NetMux class represents an LPM_MUX device. The pinout is assigned
|
|
|
|
|
* like so:
|
2005-02-12 07:25:40 +01:00
|
|
|
* 0 -- Result
|
|
|
|
|
* 1 -- Sel
|
|
|
|
|
* 2+N -- Data[N] (N is the size of the mux)
|
1999-11-04 04:53:26 +01:00
|
|
|
*/
|
|
|
|
|
|
2004-02-18 18:11:54 +01:00
|
|
|
NetMux::NetMux(NetScope*s, perm_string n,
|
2001-01-18 04:16:35 +01:00
|
|
|
unsigned wi, unsigned si, unsigned sw)
|
2005-02-12 07:25:40 +01:00
|
|
|
: NetNode(s, n, 2+si),
|
2003-03-06 01:28:41 +01:00
|
|
|
width_(wi), size_(si), swidth_(sw)
|
1999-11-04 04:53:26 +01:00
|
|
|
{
|
2008-09-11 04:34:28 +02:00
|
|
|
pin(0).set_dir(Link::OUTPUT); // Q
|
|
|
|
|
pin(1).set_dir(Link::INPUT); // Sel
|
1999-11-04 04:53:26 +01:00
|
|
|
|
2005-02-12 07:25:40 +01:00
|
|
|
for (unsigned idx = 0 ; idx < size_ ; idx += 1) {
|
2008-09-11 04:34:28 +02:00
|
|
|
pin_Data(idx).set_dir(Link::INPUT); // Data[idx]
|
1999-11-04 04:53:26 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NetMux::~NetMux()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned NetMux::width()const
|
|
|
|
|
{
|
|
|
|
|
return width_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned NetMux::size() const
|
|
|
|
|
{
|
|
|
|
|
return size_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned NetMux::sel_width() const
|
|
|
|
|
{
|
|
|
|
|
return swidth_;
|
|
|
|
|
}
|
|
|
|
|
|
2005-02-12 07:25:40 +01:00
|
|
|
Link& NetMux::pin_Result()
|
1999-11-04 04:53:26 +01:00
|
|
|
{
|
|
|
|
|
return pin(0);
|
|
|
|
|
}
|
|
|
|
|
|
2005-02-12 07:25:40 +01:00
|
|
|
const Link& NetMux::pin_Result() const
|
1999-11-04 04:53:26 +01:00
|
|
|
{
|
|
|
|
|
return pin(0);
|
|
|
|
|
}
|
|
|
|
|
|
2005-02-12 07:25:40 +01:00
|
|
|
Link& NetMux::pin_Sel()
|
1999-11-04 04:53:26 +01:00
|
|
|
{
|
|
|
|
|
return pin(1);
|
|
|
|
|
}
|
|
|
|
|
|
2005-02-12 07:25:40 +01:00
|
|
|
const Link& NetMux::pin_Sel() const
|
1999-11-04 04:53:26 +01:00
|
|
|
{
|
|
|
|
|
return pin(1);
|
|
|
|
|
}
|
|
|
|
|
|
2005-02-12 07:25:40 +01:00
|
|
|
Link& NetMux::pin_Data(unsigned s)
|
1999-11-04 04:53:26 +01:00
|
|
|
{
|
2023-04-13 22:00:34 +02:00
|
|
|
ivl_assert(*this, s < size_);
|
2005-02-12 07:25:40 +01:00
|
|
|
return pin(2+s);
|
1999-11-04 04:53:26 +01:00
|
|
|
}
|
|
|
|
|
|
2005-02-12 07:25:40 +01:00
|
|
|
const Link& NetMux::pin_Data(unsigned s) const
|
1999-11-04 04:53:26 +01:00
|
|
|
{
|
2023-04-13 22:00:34 +02:00
|
|
|
ivl_assert(*this, s < size_);
|
2005-02-12 07:25:40 +01:00
|
|
|
return pin(2+s);
|
1999-11-04 04:53:26 +01:00
|
|
|
}
|
|
|
|
|
|
2005-05-24 03:44:27 +02:00
|
|
|
NetSignExtend::NetSignExtend(NetScope*s, perm_string n, unsigned w)
|
|
|
|
|
: NetNode(s, n, 2), width_(w)
|
|
|
|
|
{
|
|
|
|
|
pin(0).set_dir(Link::OUTPUT);
|
|
|
|
|
pin(1).set_dir(Link::INPUT);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NetSignExtend::~NetSignExtend()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned NetSignExtend::width() const
|
|
|
|
|
{
|
|
|
|
|
return width_;
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-08 11:42:15 +02:00
|
|
|
NetBUFZ::NetBUFZ(NetScope*s, perm_string n, unsigned w, bool trans, int port_info_index)
|
|
|
|
|
: NetNode(s, n, 2), width_(w), transparent_(trans), port_info_index_(port_info_index)
|
1999-10-31 05:11:27 +01:00
|
|
|
{
|
|
|
|
|
pin(0).set_dir(Link::OUTPUT);
|
|
|
|
|
pin(1).set_dir(Link::INPUT);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NetBUFZ::~NetBUFZ()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
unsigned NetBUFZ::width() const
|
|
|
|
|
{
|
|
|
|
|
return width_;
|
|
|
|
|
}
|
1999-10-31 05:11:27 +01:00
|
|
|
|
2014-06-14 03:01:41 +02:00
|
|
|
NetCaseCmp::NetCaseCmp(NetScope*s, perm_string n, unsigned wid, kind_t k)
|
|
|
|
|
: NetNode(s, n, 3), width_(wid), kind_(k)
|
1999-10-10 03:59:54 +02:00
|
|
|
{
|
2008-09-11 04:34:28 +02:00
|
|
|
pin(0).set_dir(Link::OUTPUT);
|
|
|
|
|
pin(1).set_dir(Link::INPUT);
|
|
|
|
|
pin(2).set_dir(Link::INPUT);
|
1999-10-10 03:59:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NetCaseCmp::~NetCaseCmp()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2005-01-22 02:06:55 +01:00
|
|
|
unsigned NetCaseCmp::width() const
|
|
|
|
|
{
|
|
|
|
|
return width_;
|
|
|
|
|
}
|
|
|
|
|
|
1999-06-24 06:24:18 +02:00
|
|
|
NetCondit::NetCondit(NetExpr*ex, NetProc*i, NetProc*e)
|
|
|
|
|
: expr_(ex), if_(i), else_(e)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
1999-07-18 23:17:50 +02:00
|
|
|
NetCondit::~NetCondit()
|
|
|
|
|
{
|
|
|
|
|
delete expr_;
|
2010-04-14 06:29:15 +02:00
|
|
|
delete if_;
|
|
|
|
|
delete else_;
|
1999-07-18 23:17:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const NetExpr* NetCondit::expr() const
|
|
|
|
|
{
|
|
|
|
|
return expr_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NetExpr* NetCondit::expr()
|
|
|
|
|
{
|
|
|
|
|
return expr_;
|
|
|
|
|
}
|
|
|
|
|
|
2000-04-17 01:32:18 +02:00
|
|
|
void NetCondit::set_expr(NetExpr*ex)
|
|
|
|
|
{
|
|
|
|
|
delete expr_;
|
|
|
|
|
expr_ = ex;
|
|
|
|
|
}
|
|
|
|
|
|
1999-07-18 23:17:50 +02:00
|
|
|
NetProc* NetCondit::if_clause()
|
|
|
|
|
{
|
|
|
|
|
return if_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NetProc* NetCondit::else_clause()
|
|
|
|
|
{
|
|
|
|
|
return else_;
|
|
|
|
|
}
|
|
|
|
|
|
2004-02-18 18:11:54 +01:00
|
|
|
NetConst::NetConst(NetScope*s, perm_string n, verinum::V v)
|
2012-12-20 20:02:29 +01:00
|
|
|
: NetNode(s, n, 1), value_(v, 1)
|
1999-10-10 03:59:54 +02:00
|
|
|
{
|
|
|
|
|
pin(0).set_dir(Link::OUTPUT);
|
1999-12-17 04:38:46 +01:00
|
|
|
}
|
|
|
|
|
|
2004-02-18 18:11:54 +01:00
|
|
|
NetConst::NetConst(NetScope*s, perm_string n, const verinum&val)
|
2012-12-20 20:02:29 +01:00
|
|
|
: NetNode(s, n, 1), value_(val)
|
1999-12-17 04:38:46 +01:00
|
|
|
{
|
2004-12-11 03:31:25 +01:00
|
|
|
pin(0).set_dir(Link::OUTPUT);
|
1999-10-10 03:59:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NetConst::~NetConst()
|
|
|
|
|
{
|
1999-12-17 04:38:46 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
verinum::V NetConst::value(unsigned idx) const
|
|
|
|
|
{
|
2023-04-13 22:00:34 +02:00
|
|
|
ivl_assert(*this, idx < width());
|
1999-12-17 04:38:46 +01:00
|
|
|
return value_[idx];
|
1999-10-10 03:59:54 +02:00
|
|
|
}
|
|
|
|
|
|
2013-09-19 03:48:16 +02:00
|
|
|
NetBaseDef::NetBaseDef(NetScope*s, const vector<NetNet*>&po, const std::vector<NetExpr*>&pd)
|
|
|
|
|
: scope_(s), ports_(po), pdefaults_(pd)
|
1999-08-26 00:22:41 +02:00
|
|
|
{
|
2013-09-19 03:48:16 +02:00
|
|
|
proc_ = 0;
|
1999-08-26 00:22:41 +02:00
|
|
|
}
|
|
|
|
|
|
2013-09-19 03:48:16 +02:00
|
|
|
NetBaseDef::~NetBaseDef()
|
1999-08-26 00:22:41 +02:00
|
|
|
{
|
|
|
|
|
}
|
2008-09-11 04:34:28 +02:00
|
|
|
|
2013-09-19 03:48:16 +02:00
|
|
|
const NetScope* NetBaseDef::scope() const
|
2007-06-02 05:42:12 +02:00
|
|
|
{
|
|
|
|
|
return scope_;
|
|
|
|
|
}
|
1999-09-01 00:38:29 +02:00
|
|
|
|
2013-09-19 03:48:16 +02:00
|
|
|
NetScope*NetBaseDef::scope()
|
2000-03-08 05:36:53 +01:00
|
|
|
{
|
|
|
|
|
return scope_;
|
|
|
|
|
}
|
|
|
|
|
|
2013-09-19 03:48:16 +02:00
|
|
|
unsigned NetBaseDef::port_count() const
|
1999-09-01 22:46:19 +02:00
|
|
|
{
|
2012-05-29 01:49:41 +02:00
|
|
|
return ports_.size();
|
1999-09-01 22:46:19 +02:00
|
|
|
}
|
|
|
|
|
|
2013-09-19 03:48:16 +02:00
|
|
|
NetNet* NetBaseDef::port(unsigned idx) const
|
1999-09-01 22:46:19 +02:00
|
|
|
{
|
2012-05-29 01:49:41 +02:00
|
|
|
assert(idx < ports_.size());
|
1999-09-01 22:46:19 +02:00
|
|
|
return ports_[idx];
|
|
|
|
|
}
|
|
|
|
|
|
2013-09-19 03:48:16 +02:00
|
|
|
NetExpr* NetBaseDef::port_defe(unsigned idx) const
|
2013-09-15 04:54:35 +02:00
|
|
|
{
|
|
|
|
|
assert(idx < pdefaults_.size());
|
|
|
|
|
return pdefaults_[idx];
|
|
|
|
|
}
|
|
|
|
|
|
2013-09-19 03:48:16 +02:00
|
|
|
void NetBaseDef::set_proc(NetProc*st)
|
|
|
|
|
{
|
|
|
|
|
assert(proc_ == 0);
|
|
|
|
|
assert(st != 0);
|
|
|
|
|
proc_ = st;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const NetProc* NetBaseDef::proc() const
|
|
|
|
|
{
|
|
|
|
|
return proc_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NetFuncDef::NetFuncDef(NetScope*s, NetNet*result, const vector<NetNet*>&po,
|
|
|
|
|
const vector<NetExpr*>&pd)
|
|
|
|
|
: NetBaseDef(s, po, pd), result_sig_(result)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NetFuncDef::~NetFuncDef()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2004-06-01 01:34:36 +02:00
|
|
|
const NetNet* NetFuncDef::return_sig() const
|
|
|
|
|
{
|
|
|
|
|
return result_sig_;
|
|
|
|
|
}
|
|
|
|
|
|
2010-08-12 04:01:58 +02:00
|
|
|
NetSTask::NetSTask(const char*na, ivl_sfunc_as_task_t sfat,
|
2012-07-17 03:15:29 +02:00
|
|
|
const vector<NetExpr*>&pa)
|
2010-08-12 04:01:58 +02:00
|
|
|
: name_(0), sfunc_as_task_(sfat), parms_(pa)
|
1998-11-04 00:28:49 +01:00
|
|
|
{
|
2003-03-01 07:25:30 +01:00
|
|
|
name_ = lex_strings.add(na);
|
2023-04-13 22:00:34 +02:00
|
|
|
ivl_assert(*this, name_[0] == '$');
|
1999-07-03 04:12:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NetSTask::~NetSTask()
|
|
|
|
|
{
|
2012-07-17 03:15:29 +02:00
|
|
|
for (unsigned idx = 0 ; idx < parms_.size() ; idx += 1)
|
1999-05-30 03:11:46 +02:00
|
|
|
delete parms_[idx];
|
1999-03-01 04:27:53 +01:00
|
|
|
|
2003-03-01 07:25:30 +01:00
|
|
|
/* The name_ string is perm-allocated in lex_strings. */
|
2000-09-22 05:58:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const char*NetSTask::name() const
|
|
|
|
|
{
|
|
|
|
|
return name_;
|
|
|
|
|
}
|
|
|
|
|
|
2010-08-12 04:01:58 +02:00
|
|
|
ivl_sfunc_as_task_t NetSTask::sfunc_as_task() const
|
|
|
|
|
{
|
|
|
|
|
return sfunc_as_task_;
|
|
|
|
|
}
|
|
|
|
|
|
2000-09-22 05:58:30 +02:00
|
|
|
unsigned NetSTask::nparms() const
|
|
|
|
|
{
|
2012-07-17 03:15:29 +02:00
|
|
|
return parms_.size();
|
1999-07-03 04:12:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const NetExpr* NetSTask::parm(unsigned idx) const
|
|
|
|
|
{
|
|
|
|
|
return parms_[idx];
|
|
|
|
|
}
|
|
|
|
|
|
2008-02-22 23:51:53 +01:00
|
|
|
NetEUFunc::NetEUFunc(NetScope*scope, NetScope*def, NetESignal*res,
|
2012-05-29 01:49:41 +02:00
|
|
|
vector<NetExpr*>&p, bool nc)
|
2022-09-30 10:51:52 +02:00
|
|
|
: NetExpr(res->net_type()), scope_(scope), func_(def), result_sig_(res), parms_(p), need_const_(nc)
|
2004-06-01 01:34:36 +02:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
1999-09-01 00:38:29 +02:00
|
|
|
NetEUFunc::~NetEUFunc()
|
|
|
|
|
{
|
2012-05-29 01:49:41 +02:00
|
|
|
for (unsigned idx = 0 ; idx < parms_.size() ; idx += 1)
|
1999-09-01 00:38:29 +02:00
|
|
|
delete parms_[idx];
|
|
|
|
|
}
|
2007-06-02 05:42:12 +02:00
|
|
|
#if 0
|
2000-03-08 05:36:53 +01:00
|
|
|
const string NetEUFunc::name() const
|
1999-09-01 00:38:29 +02:00
|
|
|
{
|
|
|
|
|
return func_->name();
|
|
|
|
|
}
|
2007-06-02 05:42:12 +02:00
|
|
|
#endif
|
2004-06-01 01:34:36 +02:00
|
|
|
const NetESignal*NetEUFunc::result_sig() const
|
|
|
|
|
{
|
|
|
|
|
return result_sig_;
|
|
|
|
|
}
|
|
|
|
|
|
1999-09-01 22:46:19 +02:00
|
|
|
unsigned NetEUFunc::parm_count() const
|
|
|
|
|
{
|
2012-05-29 01:49:41 +02:00
|
|
|
return parms_.size();
|
1999-09-01 22:46:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const NetExpr* NetEUFunc::parm(unsigned idx) const
|
|
|
|
|
{
|
2023-04-13 22:00:34 +02:00
|
|
|
ivl_assert(*this, idx < parms_.size());
|
1999-09-01 22:46:19 +02:00
|
|
|
return parms_[idx];
|
|
|
|
|
}
|
|
|
|
|
|
2001-04-06 04:28:02 +02:00
|
|
|
const NetScope* NetEUFunc::func() const
|
1999-09-01 22:46:19 +02:00
|
|
|
{
|
|
|
|
|
return func_;
|
|
|
|
|
}
|
|
|
|
|
|
2001-04-02 04:28:12 +02:00
|
|
|
NetUTask::NetUTask(NetScope*def)
|
1999-07-24 04:11:19 +02:00
|
|
|
: task_(def)
|
1999-07-03 04:12:51 +02:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NetUTask::~NetUTask()
|
|
|
|
|
{
|
1998-11-04 00:28:49 +01:00
|
|
|
}
|
2008-09-11 04:34:28 +02:00
|
|
|
|
2001-04-02 04:28:12 +02:00
|
|
|
const NetScope* NetUTask::task() const
|
|
|
|
|
{
|
|
|
|
|
return task_;
|
|
|
|
|
}
|
|
|
|
|
|
2008-10-06 18:53:39 +02:00
|
|
|
NetAlloc::NetAlloc(NetScope*scope__)
|
|
|
|
|
: scope_(scope__)
|
2008-09-27 01:54:13 +02:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NetAlloc::~NetAlloc()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
#if 0
|
|
|
|
|
const string NetAlloc::name() const
|
|
|
|
|
{
|
|
|
|
|
return scope_->name();
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
const NetScope* NetAlloc::scope() const
|
|
|
|
|
{
|
|
|
|
|
return scope_;
|
|
|
|
|
}
|
|
|
|
|
|
2008-10-06 18:53:39 +02:00
|
|
|
NetFree::NetFree(NetScope*scope__)
|
|
|
|
|
: scope_(scope__)
|
2008-09-27 01:54:13 +02:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NetFree::~NetFree()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
#if 0
|
|
|
|
|
const string NetFree::name() const
|
|
|
|
|
{
|
|
|
|
|
return scope_->name();
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
const NetScope* NetFree::scope() const
|
|
|
|
|
{
|
|
|
|
|
return scope_;
|
|
|
|
|
}
|
|
|
|
|
|
2001-02-07 22:47:13 +01:00
|
|
|
/*
|
|
|
|
|
* Create a bitwise operator node from the opcode and the left and
|
2011-02-26 23:59:52 +01:00
|
|
|
* right expressions.
|
2001-02-07 22:47:13 +01:00
|
|
|
*/
|
2011-02-26 23:59:52 +01:00
|
|
|
NetEBBits::NetEBBits(char op__, NetExpr*l, NetExpr*r, unsigned wid, bool signed_flag)
|
|
|
|
|
: NetEBinary(op__, l, r, wid, signed_flag)
|
1999-07-31 05:16:54 +02:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NetEBBits::~NetEBBits()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-16 15:44:56 +02:00
|
|
|
ivl_variable_type_t NetEBBits::expr_type() const
|
|
|
|
|
{
|
|
|
|
|
if (left_->expr_type() == IVL_VT_LOGIC ||
|
|
|
|
|
right_->expr_type() == IVL_VT_LOGIC)
|
|
|
|
|
return IVL_VT_LOGIC;
|
|
|
|
|
|
|
|
|
|
return IVL_VT_BOOL;
|
|
|
|
|
}
|
|
|
|
|
|
2011-02-26 23:59:52 +01:00
|
|
|
NetEBinary::NetEBinary(char op__, NetExpr*l, NetExpr*r, unsigned wid, bool signed_flag)
|
2008-10-06 18:53:39 +02:00
|
|
|
: op_(op__), left_(l), right_(r)
|
1999-03-01 04:27:53 +01:00
|
|
|
{
|
2011-02-26 23:59:52 +01:00
|
|
|
expr_width(wid);
|
|
|
|
|
cast_signed_base_(signed_flag);
|
1999-03-01 04:27:53 +01:00
|
|
|
}
|
1998-11-07 20:17:10 +01:00
|
|
|
|
|
|
|
|
NetEBinary::~NetEBinary()
|
1998-11-04 00:28:49 +01:00
|
|
|
{
|
1999-05-30 03:11:46 +02:00
|
|
|
delete left_;
|
|
|
|
|
delete right_;
|
1998-11-07 20:17:10 +01:00
|
|
|
}
|
|
|
|
|
|
2001-02-10 22:20:38 +01:00
|
|
|
bool NetEBinary::has_width() const
|
|
|
|
|
{
|
|
|
|
|
return left_->has_width() && right_->has_width();
|
|
|
|
|
}
|
|
|
|
|
|
2008-10-06 18:53:39 +02:00
|
|
|
NetEBLogic::NetEBLogic(char op__, NetExpr*l, NetExpr*r)
|
2011-02-26 23:59:52 +01:00
|
|
|
: NetEBinary(op__, l, r, 1, false)
|
1999-09-23 02:21:54 +02:00
|
|
|
{
|
1998-11-07 18:05:05 +01:00
|
|
|
}
|
|
|
|
|
|
1999-09-23 02:21:54 +02:00
|
|
|
NetEBLogic::~NetEBLogic()
|
1999-05-30 03:11:46 +02:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-16 15:44:56 +02:00
|
|
|
ivl_variable_type_t NetEBLogic::expr_type() const
|
|
|
|
|
{
|
|
|
|
|
if (left_->expr_type() == IVL_VT_LOGIC ||
|
|
|
|
|
right_->expr_type() == IVL_VT_LOGIC)
|
|
|
|
|
return IVL_VT_LOGIC;
|
|
|
|
|
|
|
|
|
|
return IVL_VT_BOOL;
|
|
|
|
|
}
|
|
|
|
|
|
1999-09-20 04:21:10 +02:00
|
|
|
NetEConst::NetEConst(const verinum&val)
|
|
|
|
|
: NetExpr(val.len()), value_(val)
|
|
|
|
|
{
|
2007-12-18 06:00:18 +01:00
|
|
|
cast_signed_base_(value_.has_sign());
|
1999-09-20 04:21:10 +02:00
|
|
|
}
|
|
|
|
|
|
2022-09-30 10:51:52 +02:00
|
|
|
NetEConst::NetEConst(ivl_type_t type, const verinum&val)
|
|
|
|
|
: NetExpr(type), value_(val)
|
|
|
|
|
{
|
|
|
|
|
ivl_assert(*this, type->packed());
|
|
|
|
|
ivl_assert(*this, type->packed_width() == val.len());
|
|
|
|
|
ivl_assert(*this, type->get_signed() == val.has_sign());
|
|
|
|
|
}
|
|
|
|
|
|
1998-11-07 20:17:10 +01:00
|
|
|
NetEConst::~NetEConst()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2011-02-26 23:59:52 +01:00
|
|
|
void NetEConst::cast_signed(bool flag)
|
|
|
|
|
{
|
|
|
|
|
cast_signed_base_(flag);
|
|
|
|
|
value_.has_sign(flag);
|
|
|
|
|
}
|
|
|
|
|
|
2000-09-26 07:05:58 +02:00
|
|
|
const verinum& NetEConst::value() const
|
|
|
|
|
{
|
|
|
|
|
return value_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool NetEConst::has_width() const
|
|
|
|
|
{
|
|
|
|
|
return value_.has_len();
|
|
|
|
|
}
|
|
|
|
|
|
2005-09-14 04:53:13 +02:00
|
|
|
ivl_variable_type_t NetEConst::expr_type() const
|
|
|
|
|
{
|
|
|
|
|
if (value_.len() == 0)
|
|
|
|
|
return IVL_VT_LOGIC;
|
|
|
|
|
if (value_.is_string())
|
|
|
|
|
return IVL_VT_BOOL;
|
|
|
|
|
if (value_.is_defined())
|
|
|
|
|
return IVL_VT_BOOL;
|
|
|
|
|
|
|
|
|
|
return IVL_VT_LOGIC;
|
|
|
|
|
}
|
|
|
|
|
|
2011-02-26 23:59:52 +01:00
|
|
|
void NetEConst::trim()
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
if (value_.is_string())
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
value_.has_len(false);
|
|
|
|
|
value_ = trim_vnum(value_);
|
|
|
|
|
expr_width(value_.len());
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-19 12:08:57 +01:00
|
|
|
NetEConstParam::NetEConstParam(const NetScope*s, perm_string n, const verinum&v)
|
2003-03-11 00:40:53 +01:00
|
|
|
: NetEConst(v), scope_(s), name_(n)
|
1999-05-30 03:11:46 +02:00
|
|
|
{
|
2008-12-19 06:33:31 +01:00
|
|
|
cast_signed_base_(v.has_sign());
|
1999-05-30 03:11:46 +02:00
|
|
|
}
|
|
|
|
|
|
2003-03-11 00:40:53 +01:00
|
|
|
NetEConstParam::~NetEConstParam()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2004-02-20 07:22:56 +01:00
|
|
|
perm_string NetEConstParam::name() const
|
2003-03-11 00:40:53 +01:00
|
|
|
{
|
|
|
|
|
return name_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const NetScope* NetEConstParam::scope() const
|
|
|
|
|
{
|
|
|
|
|
return scope_;
|
|
|
|
|
}
|
|
|
|
|
|
2003-04-22 06:48:29 +02:00
|
|
|
NetEEvent::NetEEvent(NetEvent*e)
|
|
|
|
|
: event_(e)
|
|
|
|
|
{
|
|
|
|
|
e->exprref_ += 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NetEEvent::~NetEEvent()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const NetEvent* NetEEvent::event() const
|
|
|
|
|
{
|
|
|
|
|
return event_;
|
|
|
|
|
}
|
|
|
|
|
|
1999-11-27 20:07:57 +01:00
|
|
|
NetEScope::NetEScope(NetScope*s)
|
|
|
|
|
: scope_(s)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NetEScope::~NetEScope()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const NetScope* NetEScope::scope() const
|
|
|
|
|
{
|
|
|
|
|
return scope_;
|
|
|
|
|
}
|
|
|
|
|
|
1999-02-08 03:49:56 +01:00
|
|
|
NetESignal::NetESignal(NetNet*n)
|
2022-09-30 10:51:52 +02:00
|
|
|
: NetExpr(n->net_type()), net_(n), word_(0)
|
1999-02-08 03:49:56 +01:00
|
|
|
{
|
2001-07-27 06:51:44 +02:00
|
|
|
net_->incr_eref();
|
|
|
|
|
set_line(*n);
|
|
|
|
|
}
|
|
|
|
|
|
2007-01-16 06:44:14 +01:00
|
|
|
NetESignal::NetESignal(NetNet*n, NetExpr*w)
|
|
|
|
|
: NetExpr(n->vector_width()), net_(n), word_(w)
|
2001-07-27 06:51:44 +02:00
|
|
|
{
|
1999-11-29 00:42:02 +01:00
|
|
|
net_->incr_eref();
|
1999-06-02 17:38:46 +02:00
|
|
|
set_line(*n);
|
2022-09-30 10:51:52 +02:00
|
|
|
|
|
|
|
|
if (word_)
|
|
|
|
|
set_net_type(net_->net_type());
|
2023-06-25 17:21:19 +02:00
|
|
|
else
|
|
|
|
|
set_net_type(net_->array_type());
|
1999-02-08 03:49:56 +01:00
|
|
|
}
|
|
|
|
|
|
1999-11-29 00:42:02 +01:00
|
|
|
NetESignal::~NetESignal()
|
1999-07-17 05:08:31 +02:00
|
|
|
{
|
1999-11-29 00:42:02 +01:00
|
|
|
net_->decr_eref();
|
1999-07-17 05:08:31 +02:00
|
|
|
}
|
|
|
|
|
|
2004-02-18 18:11:54 +01:00
|
|
|
perm_string NetESignal::name() const
|
1998-11-07 20:17:10 +01:00
|
|
|
{
|
1999-11-29 00:42:02 +01:00
|
|
|
return net_->name();
|
|
|
|
|
}
|
|
|
|
|
|
2007-01-16 06:44:14 +01:00
|
|
|
const NetExpr* NetESignal::word_index() const
|
1999-11-29 00:42:02 +01:00
|
|
|
{
|
2007-01-16 06:44:14 +01:00
|
|
|
return word_;
|
1999-11-29 00:42:02 +01:00
|
|
|
}
|
|
|
|
|
|
2007-01-16 06:44:14 +01:00
|
|
|
unsigned NetESignal::vector_width() const
|
1999-11-29 00:42:02 +01:00
|
|
|
{
|
2007-01-16 06:44:14 +01:00
|
|
|
return net_->vector_width();
|
1998-11-07 20:17:10 +01:00
|
|
|
}
|
|
|
|
|
|
2001-07-22 02:17:49 +02:00
|
|
|
const NetNet* NetESignal::sig() const
|
|
|
|
|
{
|
|
|
|
|
return net_;
|
|
|
|
|
}
|
|
|
|
|
|
2007-01-16 06:44:14 +01:00
|
|
|
NetNet* NetESignal::sig()
|
|
|
|
|
{
|
|
|
|
|
return net_;
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-07 02:47:53 +01:00
|
|
|
/*
|
|
|
|
|
* The lsi() and msi() methods should be removed from the NetESignal
|
|
|
|
|
* class, to be replaced with packed dimensions aware methods of
|
|
|
|
|
* getting at dimensions.
|
|
|
|
|
*/
|
2009-08-29 01:50:59 +02:00
|
|
|
long NetESignal::lsi() const
|
2001-07-27 06:51:44 +02:00
|
|
|
{
|
2022-01-06 15:24:20 +01:00
|
|
|
const netranges_t&packed = net_->packed_dims();
|
2012-02-07 02:47:53 +01:00
|
|
|
ivl_assert(*this, packed.size() == 1);
|
2012-07-14 03:41:41 +02:00
|
|
|
return packed.back().get_lsb();
|
2001-07-27 06:51:44 +02:00
|
|
|
}
|
|
|
|
|
|
2009-08-29 01:50:59 +02:00
|
|
|
long NetESignal::msi() const
|
2001-07-27 06:51:44 +02:00
|
|
|
{
|
2022-01-06 15:24:20 +01:00
|
|
|
const netranges_t&packed = net_->packed_dims();
|
2012-02-07 02:47:53 +01:00
|
|
|
ivl_assert(*this, packed.size() == 1);
|
2012-07-14 03:41:41 +02:00
|
|
|
return packed.back().get_msb();
|
2001-07-27 06:51:44 +02:00
|
|
|
}
|
|
|
|
|
|
2005-07-11 18:56:50 +02:00
|
|
|
ivl_variable_type_t NetESignal::expr_type() const
|
|
|
|
|
{
|
2012-07-22 02:33:10 +02:00
|
|
|
if (net_->darray_type())
|
|
|
|
|
return IVL_VT_DARRAY;
|
|
|
|
|
else
|
|
|
|
|
return net_->data_type();
|
2005-07-11 18:56:50 +02:00
|
|
|
}
|
|
|
|
|
|
2006-11-10 05:54:26 +01:00
|
|
|
/*
|
|
|
|
|
* Make a ternary operator from all the sub-expressions. The condition
|
|
|
|
|
* expression is self-determined, but the true and false expressions
|
|
|
|
|
* should have the same width. NOTE: This matching of the widths really
|
|
|
|
|
* has to be done in elaboration.
|
|
|
|
|
*/
|
2011-02-26 23:59:52 +01:00
|
|
|
NetETernary::NetETernary(NetExpr*c, NetExpr*t, NetExpr*f,
|
|
|
|
|
unsigned wid, bool signed_flag)
|
1999-07-17 21:50:59 +02:00
|
|
|
: cond_(c), true_val_(t), false_val_(f)
|
|
|
|
|
{
|
2011-02-26 23:59:52 +01:00
|
|
|
expr_width(wid);
|
|
|
|
|
cast_signed_base_(signed_flag);
|
1999-07-17 21:50:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NetETernary::~NetETernary()
|
|
|
|
|
{
|
|
|
|
|
delete cond_;
|
|
|
|
|
delete true_val_;
|
|
|
|
|
delete false_val_;
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-09 14:11:16 +01:00
|
|
|
const netenum_t* NetETernary::enumeration() const
|
|
|
|
|
{
|
|
|
|
|
// If the condition can evaluate to an ambiguous value,
|
|
|
|
|
// the result may be blended, and so is not guaranteed
|
|
|
|
|
// to be a valid enumeration value.
|
|
|
|
|
if (cond_->expr_type() != IVL_VT_BOOL)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
if (true_val_->enumeration() != false_val_->enumeration())
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
return true_val_->enumeration();
|
|
|
|
|
}
|
|
|
|
|
|
1999-09-11 06:43:17 +02:00
|
|
|
const NetExpr* NetETernary::cond_expr() const
|
|
|
|
|
{
|
|
|
|
|
return cond_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const NetExpr* NetETernary::true_expr() const
|
|
|
|
|
{
|
|
|
|
|
return true_val_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const NetExpr* NetETernary::false_expr() const
|
|
|
|
|
{
|
|
|
|
|
return false_val_;
|
|
|
|
|
}
|
|
|
|
|
|
2007-02-14 06:59:46 +01:00
|
|
|
ivl_variable_type_t NetETernary::expr_type() const
|
|
|
|
|
{
|
2008-08-13 06:31:39 +02:00
|
|
|
ivl_assert(*this, true_val_);
|
|
|
|
|
ivl_assert(*this, false_val_);
|
2007-02-14 06:59:46 +01:00
|
|
|
ivl_variable_type_t tru = true_val_->expr_type();
|
|
|
|
|
ivl_variable_type_t fal = false_val_->expr_type();
|
2010-10-14 05:07:44 +02:00
|
|
|
ivl_variable_type_t sel = cond_->expr_type();
|
2007-02-14 06:59:46 +01:00
|
|
|
if (tru == IVL_VT_LOGIC && fal == IVL_VT_BOOL)
|
|
|
|
|
return IVL_VT_LOGIC;
|
|
|
|
|
if (tru == IVL_VT_BOOL && fal == IVL_VT_LOGIC)
|
|
|
|
|
return IVL_VT_LOGIC;
|
2010-10-14 05:07:44 +02:00
|
|
|
if (sel == IVL_VT_LOGIC && (tru == IVL_VT_LOGIC || tru == IVL_VT_BOOL) && (fal == IVL_VT_LOGIC || fal == IVL_VT_BOOL))
|
|
|
|
|
return IVL_VT_LOGIC;
|
2008-03-08 03:51:50 +01:00
|
|
|
if (tru == IVL_VT_REAL && (fal == IVL_VT_LOGIC || fal == IVL_VT_BOOL))
|
|
|
|
|
return IVL_VT_REAL;
|
|
|
|
|
if (fal == IVL_VT_REAL && (tru == IVL_VT_LOGIC || tru == IVL_VT_BOOL))
|
|
|
|
|
return IVL_VT_REAL;
|
|
|
|
|
|
2007-06-30 06:10:37 +02:00
|
|
|
if (tru != fal) {
|
2007-12-20 18:31:01 +01:00
|
|
|
cerr << get_fileline() << ": internal error:"
|
2007-06-30 06:10:37 +02:00
|
|
|
<< " Unexpected ?: type clash:"
|
|
|
|
|
<< " tru=" << tru << ", fal=" << fal << endl;
|
|
|
|
|
}
|
2007-02-14 06:59:46 +01:00
|
|
|
ivl_assert(*this, tru == fal);
|
|
|
|
|
return tru;
|
|
|
|
|
}
|
|
|
|
|
|
2011-02-26 23:59:52 +01:00
|
|
|
NetEUnary::NetEUnary(char op__, NetExpr*ex, unsigned wid, bool signed_flag)
|
|
|
|
|
: NetExpr(wid), op_(op__), expr_(ex)
|
1999-09-28 05:11:29 +02:00
|
|
|
{
|
2011-02-26 23:59:52 +01:00
|
|
|
cast_signed_base_(signed_flag);
|
1999-09-28 05:11:29 +02:00
|
|
|
}
|
|
|
|
|
|
1998-11-07 20:17:10 +01:00
|
|
|
NetEUnary::~NetEUnary()
|
|
|
|
|
{
|
1999-05-30 03:11:46 +02:00
|
|
|
delete expr_;
|
1998-11-07 20:17:10 +01:00
|
|
|
}
|
|
|
|
|
|
2007-02-20 06:58:36 +01:00
|
|
|
ivl_variable_type_t NetEUnary::expr_type() const
|
|
|
|
|
{
|
|
|
|
|
return expr_->expr_type();
|
|
|
|
|
}
|
|
|
|
|
|
2011-02-26 23:59:52 +01:00
|
|
|
NetEUBits::NetEUBits(char op__, NetExpr*ex, unsigned wid, bool signed_flag)
|
|
|
|
|
: NetEUnary(op__, ex, wid, signed_flag)
|
1999-11-04 04:53:26 +01:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NetEUBits::~NetEUBits()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2007-02-20 06:58:36 +01:00
|
|
|
ivl_variable_type_t NetEUBits::expr_type() const
|
|
|
|
|
{
|
|
|
|
|
return expr_->expr_type();
|
|
|
|
|
}
|
|
|
|
|
|
2008-10-06 18:53:39 +02:00
|
|
|
NetEUReduce::NetEUReduce(char op__, NetExpr*ex)
|
2011-02-26 23:59:52 +01:00
|
|
|
: NetEUnary(op__, ex, 1, false)
|
2000-11-29 06:24:00 +01:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NetEUReduce::~NetEUReduce()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2007-02-20 06:58:36 +01:00
|
|
|
ivl_variable_type_t NetEUReduce::expr_type() const
|
|
|
|
|
{
|
|
|
|
|
return expr_->expr_type();
|
|
|
|
|
}
|
|
|
|
|
|
2011-02-26 23:59:52 +01:00
|
|
|
NetECast::NetECast(char op__, NetExpr*ex, unsigned wid, bool signed_flag)
|
|
|
|
|
: NetEUnary(op__, ex, wid, signed_flag)
|
2010-06-19 01:03:17 +02:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NetECast::~NetECast()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ivl_variable_type_t NetECast::expr_type() const
|
|
|
|
|
{
|
2012-01-06 02:24:37 +01:00
|
|
|
ivl_variable_type_t ret = IVL_VT_NO_TYPE;
|
2010-06-19 01:03:17 +02:00
|
|
|
switch (op_) {
|
2011-08-07 00:27:39 +02:00
|
|
|
case 'v':
|
2010-06-19 01:03:17 +02:00
|
|
|
ret = IVL_VT_LOGIC;
|
|
|
|
|
break;
|
|
|
|
|
case 'r':
|
|
|
|
|
ret = IVL_VT_REAL;
|
|
|
|
|
break;
|
2010-10-16 19:53:20 +02:00
|
|
|
case '2':
|
|
|
|
|
ret = IVL_VT_BOOL;
|
|
|
|
|
break;
|
2010-06-19 01:03:17 +02:00
|
|
|
default:
|
2023-04-13 22:00:34 +02:00
|
|
|
ivl_assert(*this, 0);
|
2010-06-19 01:03:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
NetLogic::NetLogic(NetScope*s, perm_string n, unsigned pins,
|
2011-03-22 18:58:18 +01:00
|
|
|
TYPE t, unsigned wid, bool is_cassign__)
|
|
|
|
|
: NetNode(s, n, pins), type_(t), width_(wid), is_cassign_(is_cassign__)
|
1998-12-02 05:37:13 +01:00
|
|
|
{
|
|
|
|
|
pin(0).set_dir(Link::OUTPUT);
|
1999-10-31 05:11:27 +01:00
|
|
|
for (unsigned idx = 1 ; idx < pins ; idx += 1) {
|
1998-12-02 05:37:13 +01:00
|
|
|
pin(idx).set_dir(Link::INPUT);
|
1999-10-31 05:11:27 +01:00
|
|
|
}
|
1998-12-02 05:37:13 +01:00
|
|
|
}
|
|
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
NetLogic::TYPE NetLogic::type() const
|
|
|
|
|
{
|
|
|
|
|
return type_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned NetLogic::width() const
|
|
|
|
|
{
|
|
|
|
|
return width_;
|
|
|
|
|
}
|
|
|
|
|
|
2011-03-22 18:58:18 +01:00
|
|
|
bool NetLogic::is_cassign() const
|
|
|
|
|
{
|
|
|
|
|
return is_cassign_;
|
|
|
|
|
}
|
|
|
|
|
|
2008-10-06 18:53:39 +02:00
|
|
|
NetUReduce::NetUReduce(NetScope*scope__, perm_string n,
|
2005-02-03 05:56:20 +01:00
|
|
|
NetUReduce::TYPE t, unsigned wid)
|
2008-10-06 18:53:39 +02:00
|
|
|
: NetNode(scope__, n, 2), type_(t), width_(wid)
|
2005-02-03 05:56:20 +01:00
|
|
|
{
|
|
|
|
|
pin(0).set_dir(Link::OUTPUT);
|
|
|
|
|
pin(1).set_dir(Link::INPUT);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NetUReduce::TYPE NetUReduce::type() const
|
|
|
|
|
{
|
|
|
|
|
return type_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned NetUReduce::width() const
|
|
|
|
|
{
|
|
|
|
|
return width_;
|
|
|
|
|
}
|
|
|
|
|
|
2013-09-15 04:54:35 +02:00
|
|
|
NetTaskDef::NetTaskDef(NetScope*n, const vector<NetNet*>&po, const vector<NetExpr*>&pd)
|
2013-09-19 03:48:16 +02:00
|
|
|
: NetBaseDef(n, po, pd)
|
1999-07-03 04:12:51 +02:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NetTaskDef::~NetTaskDef()
|
|
|
|
|
{
|
|
|
|
|
delete proc_;
|
|
|
|
|
}
|
|
|
|
|
|
2008-04-22 20:32:10 +02:00
|
|
|
/*
|
|
|
|
|
* These are the delay_type() functions. They are used to determine
|
|
|
|
|
* the type of delay for the given object.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* This function implements the following table:
|
|
|
|
|
*
|
|
|
|
|
* in_A in_B out
|
|
|
|
|
* NO NO NO
|
|
|
|
|
* NO ZERO ZERO
|
|
|
|
|
* NO POS POS
|
|
|
|
|
* NO DEF POS
|
|
|
|
|
* ZERO NO ZERO
|
|
|
|
|
* ZERO ZERO ZERO
|
|
|
|
|
* ZERO POS POS
|
|
|
|
|
* ZERO DEF POS
|
|
|
|
|
* POS NO POS
|
|
|
|
|
* POS ZERO POS
|
|
|
|
|
* POS POS POS
|
|
|
|
|
* POS DEF POS
|
|
|
|
|
* DEF NO POS
|
|
|
|
|
* DEF ZERO POS
|
|
|
|
|
* DEF POS POS
|
|
|
|
|
* DEF DEF DEF
|
|
|
|
|
*
|
|
|
|
|
* It is used to combine two delay values.
|
|
|
|
|
*/
|
|
|
|
|
static DelayType combine_delays(const DelayType a, const DelayType b)
|
|
|
|
|
{
|
|
|
|
|
/* The default is POSSIBLE_DELAY. */
|
|
|
|
|
DelayType result = POSSIBLE_DELAY;
|
|
|
|
|
|
|
|
|
|
/* If both are no or zero delay then we return ZERO_DELAY. */
|
|
|
|
|
if ((a == NO_DELAY || a == ZERO_DELAY) &&
|
|
|
|
|
(b == NO_DELAY || b == ZERO_DELAY)) {
|
|
|
|
|
result = ZERO_DELAY;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Except if both are no delay then we return NO_DELAY. */
|
|
|
|
|
if (a == NO_DELAY && b == NO_DELAY) {
|
|
|
|
|
result = NO_DELAY;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* If both are definite delay then we return DEFINITE_DELAY. */
|
|
|
|
|
if (a == DEFINITE_DELAY && b == DEFINITE_DELAY) {
|
|
|
|
|
result = DEFINITE_DELAY;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* This is used to see what we can find out about the delay when it
|
|
|
|
|
* is given as an expression. We also use this for loop expressions.
|
|
|
|
|
*/
|
|
|
|
|
static DelayType delay_type_from_expr(const NetExpr*expr)
|
|
|
|
|
{
|
|
|
|
|
DelayType result = POSSIBLE_DELAY;
|
|
|
|
|
|
|
|
|
|
if (const NetEConst*e = dynamic_cast<const NetEConst*>(expr)) {
|
|
|
|
|
if (e->value().is_zero()) result = ZERO_DELAY;
|
|
|
|
|
else result = DEFINITE_DELAY;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (const NetECReal*e = dynamic_cast<const NetECReal*>(expr)) {
|
|
|
|
|
if (e->value().as_double() == 0.0) result = ZERO_DELAY;
|
|
|
|
|
else result = DEFINITE_DELAY;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* The looping structures can use the same basic code so put it here
|
|
|
|
|
* instead of duplicating it for each one (repeat and while).
|
|
|
|
|
*/
|
2017-12-06 09:21:24 +01:00
|
|
|
static DelayType get_loop_delay_type(const NetExpr*expr, const NetProc*proc, bool print_delay)
|
2008-04-22 20:32:10 +02:00
|
|
|
{
|
|
|
|
|
DelayType result;
|
|
|
|
|
|
|
|
|
|
switch (delay_type_from_expr(expr)) {
|
|
|
|
|
/* We have a constant false expression so the body never runs. */
|
|
|
|
|
case ZERO_DELAY:
|
|
|
|
|
result = NO_DELAY;
|
|
|
|
|
break;
|
|
|
|
|
/* We have a constant true expression so the body always runs. */
|
|
|
|
|
case DEFINITE_DELAY:
|
2017-12-27 23:41:43 +01:00
|
|
|
if (proc) {
|
|
|
|
|
result = proc->delay_type(print_delay);
|
|
|
|
|
} else {
|
|
|
|
|
result = NO_DELAY;
|
|
|
|
|
}
|
2008-04-22 20:32:10 +02:00
|
|
|
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:
|
2017-12-27 23:41:43 +01:00
|
|
|
if (proc) {
|
|
|
|
|
result = combine_delays(NO_DELAY, proc->delay_type(print_delay));
|
|
|
|
|
} else {
|
|
|
|
|
result = NO_DELAY;
|
|
|
|
|
}
|
2008-04-22 20:32:10 +02:00
|
|
|
break;
|
|
|
|
|
/* This should never happen since delay_type_from_expr() only
|
|
|
|
|
* returns three different values. */
|
|
|
|
|
default:
|
2009-12-10 22:58:50 +01:00
|
|
|
result = NO_DELAY;
|
2023-04-13 22:00:34 +02:00
|
|
|
ivl_assert(*expr, 0);
|
2008-04-22 20:32:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* The default object does not have any delay. */
|
2017-12-06 09:21:24 +01:00
|
|
|
DelayType NetProc::delay_type(bool /* print_delay */ ) const
|
2008-04-22 20:32:10 +02:00
|
|
|
{
|
|
|
|
|
return NO_DELAY;
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-06 09:21:24 +01:00
|
|
|
DelayType NetBlock::delay_type(bool print_delay) const
|
2008-04-22 20:32:10 +02:00
|
|
|
{
|
2017-12-06 06:48:33 +01:00
|
|
|
// A join_none has no delay.
|
|
|
|
|
if (type() == PARA_JOIN_NONE) return NO_DELAY;
|
|
|
|
|
|
|
|
|
|
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)) {
|
2017-12-06 09:21:24 +01:00
|
|
|
DelayType dt = cur->delay_type(print_delay);
|
2017-12-06 06:48:33 +01:00
|
|
|
if (dt < result) result = dt;
|
2017-12-27 23:41:43 +01:00
|
|
|
if ((dt == NO_DELAY) && !print_delay) break;
|
2017-12-06 06:48:33 +01:00
|
|
|
}
|
2008-04-22 20:32:10 +02:00
|
|
|
|
2017-12-06 06:48:33 +01:00
|
|
|
// A begin or join has the maximum delay.
|
|
|
|
|
} else {
|
|
|
|
|
result = NO_DELAY;
|
|
|
|
|
for (const NetProc*cur = proc_first(); cur; cur = proc_next(cur)) {
|
2017-12-06 09:21:24 +01:00
|
|
|
DelayType dt = cur->delay_type(print_delay);
|
2017-12-06 06:48:33 +01:00
|
|
|
if (dt > result) result = dt;
|
2017-12-27 23:41:43 +01:00
|
|
|
if ((dt == DEFINITE_DELAY) && !print_delay) break;
|
2017-12-06 06:48:33 +01:00
|
|
|
}
|
2008-04-22 20:32:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-06 09:21:24 +01:00
|
|
|
DelayType NetCase::delay_type(bool print_delay) const
|
2008-04-22 20:32:10 +02:00
|
|
|
{
|
|
|
|
|
DelayType result = NO_DELAY;
|
|
|
|
|
bool def_stmt = false;
|
|
|
|
|
unsigned nstmts = nitems();
|
|
|
|
|
|
|
|
|
|
for (unsigned idx = 0; idx < nstmts; idx += 1) {
|
|
|
|
|
if (!expr(idx)) def_stmt = true;
|
2017-12-06 09:21:24 +01:00
|
|
|
DelayType dt = stat(idx) ? stat(idx)->delay_type(print_delay) : NO_DELAY;
|
2008-04-22 20:32:10 +02:00
|
|
|
if (idx == 0) {
|
2015-08-17 22:47:15 +02:00
|
|
|
result = dt;
|
2008-04-22 20:32:10 +02:00
|
|
|
} else {
|
2015-08-17 22:47:15 +02:00
|
|
|
result = combine_delays(result, dt);
|
2008-04-22 20:32:10 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-27 23:41:43 +01:00
|
|
|
// FIXME: If all the cases are covered (e.g. an enum) then this is not true.
|
2008-04-22 20:32:10 +02:00
|
|
|
/* 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);
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-06 09:21:24 +01:00
|
|
|
DelayType NetCondit::delay_type(bool print_delay) const
|
2008-04-22 20:32:10 +02:00
|
|
|
{
|
2017-12-06 09:21:24 +01:00
|
|
|
DelayType if_type = if_ ? if_->delay_type(print_delay) : NO_DELAY;
|
|
|
|
|
DelayType el_type = else_? else_->delay_type(print_delay) : NO_DELAY;
|
2010-10-02 19:38:59 +02:00
|
|
|
return combine_delays(if_type, el_type);
|
2008-04-22 20:32:10 +02:00
|
|
|
}
|
|
|
|
|
|
2013-09-17 05:01:06 +02:00
|
|
|
/*
|
|
|
|
|
* A do/while will execute the body at least once.
|
|
|
|
|
*/
|
2017-12-06 09:21:24 +01:00
|
|
|
DelayType NetDoWhile::delay_type(bool print_delay) const
|
2013-09-17 05:01:06 +02:00
|
|
|
{
|
2017-12-27 23:41:43 +01:00
|
|
|
if (proc_) return proc_->delay_type(print_delay);
|
|
|
|
|
|
|
|
|
|
return ZERO_DELAY;
|
2013-09-17 05:01:06 +02:00
|
|
|
}
|
|
|
|
|
|
2017-12-06 09:21:24 +01:00
|
|
|
DelayType NetEvWait::delay_type(bool print_delay) const
|
2008-04-22 20:32:10 +02:00
|
|
|
{
|
2017-12-06 09:21:24 +01:00
|
|
|
if (print_delay) {
|
|
|
|
|
cerr << get_fileline() << ": error: an event control is not allowed "
|
2017-12-27 23:41:43 +01:00
|
|
|
"in an always_comb, always_ff or always_latch process."
|
2017-12-06 09:21:24 +01:00
|
|
|
<< endl;
|
|
|
|
|
}
|
2017-12-27 23:41:43 +01:00
|
|
|
|
2008-04-22 20:32:10 +02:00
|
|
|
return DEFINITE_DELAY;
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-06 09:21:24 +01:00
|
|
|
DelayType NetForever::delay_type(bool print_delay) const
|
2008-04-22 20:32:10 +02:00
|
|
|
{
|
2017-12-27 23:41:43 +01:00
|
|
|
if (statement_) return statement_->delay_type(print_delay);
|
|
|
|
|
|
|
|
|
|
return ZERO_DELAY;
|
2008-04-22 20:32:10 +02:00
|
|
|
}
|
|
|
|
|
|
2017-12-06 09:21:24 +01:00
|
|
|
DelayType NetForLoop::delay_type(bool print_delay) const
|
2014-05-02 05:37:33 +02:00
|
|
|
{
|
2017-12-06 09:21:24 +01:00
|
|
|
return get_loop_delay_type(condition_, statement_, print_delay);
|
2014-05-02 05:37:33 +02:00
|
|
|
}
|
|
|
|
|
|
2017-12-06 09:21:24 +01:00
|
|
|
DelayType NetPDelay::delay_type(bool print_delay) const
|
2008-04-22 20:32:10 +02:00
|
|
|
{
|
2017-12-06 09:21:24 +01:00
|
|
|
if (print_delay) {
|
|
|
|
|
cerr << get_fileline() << ": error: a blocking delay is not allowed "
|
2017-12-27 23:41:43 +01:00
|
|
|
"in an always_comb, always_ff or always_latch process."
|
2017-12-06 09:21:24 +01:00
|
|
|
<< endl;
|
|
|
|
|
}
|
2017-12-27 23:41:43 +01:00
|
|
|
|
2008-04-22 20:32:10 +02:00
|
|
|
if (expr_) {
|
2017-12-27 23:41:43 +01:00
|
|
|
if (statement_) {
|
|
|
|
|
return combine_delays(delay_type_from_expr(expr_),
|
|
|
|
|
statement_->delay_type(print_delay));
|
2008-04-22 20:32:10 +02:00
|
|
|
} else {
|
2017-12-27 23:41:43 +01:00
|
|
|
return delay_type_from_expr(expr_);
|
2008-04-22 20:32:10 +02:00
|
|
|
}
|
|
|
|
|
}
|
2017-12-27 23:41:43 +01:00
|
|
|
|
|
|
|
|
if (delay() > 0) return DEFINITE_DELAY;
|
|
|
|
|
|
|
|
|
|
if (statement_) {
|
|
|
|
|
return combine_delays(ZERO_DELAY,
|
|
|
|
|
statement_->delay_type(print_delay));
|
|
|
|
|
} else {
|
|
|
|
|
return ZERO_DELAY;
|
|
|
|
|
}
|
2008-04-22 20:32:10 +02:00
|
|
|
}
|
|
|
|
|
|
2017-12-06 09:21:24 +01:00
|
|
|
DelayType NetRepeat::delay_type(bool print_delay) const
|
2008-04-22 20:32:10 +02:00
|
|
|
{
|
2017-12-06 09:21:24 +01:00
|
|
|
return get_loop_delay_type(expr_, statement_, print_delay);
|
2008-04-22 20:32:10 +02:00
|
|
|
}
|
|
|
|
|
|
2017-12-06 09:21:24 +01:00
|
|
|
DelayType NetTaskDef::delay_type(bool print_delay) const
|
2008-04-22 20:32:10 +02:00
|
|
|
{
|
2017-12-28 17:49:12 +01:00
|
|
|
if (proc_) {
|
|
|
|
|
return proc_->delay_type(print_delay);
|
|
|
|
|
} else {
|
|
|
|
|
return NO_DELAY;
|
|
|
|
|
}
|
2008-04-22 20:32:10 +02:00
|
|
|
}
|
|
|
|
|
|
2017-12-06 09:21:24 +01:00
|
|
|
DelayType NetUTask::delay_type(bool print_delay) const
|
2008-04-22 20:32:10 +02:00
|
|
|
{
|
2020-12-27 21:53:29 +01:00
|
|
|
// Is this a void function call in a final block?
|
|
|
|
|
if (task()->type() == NetScope::FUNC) {
|
|
|
|
|
return NO_DELAY;
|
|
|
|
|
} else {
|
|
|
|
|
return task()->task_def()->delay_type(print_delay);
|
|
|
|
|
}
|
2008-04-22 20:32:10 +02:00
|
|
|
}
|
|
|
|
|
|
2017-12-27 23:41:43 +01:00
|
|
|
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.
|
2018-08-31 07:29:22 +02:00
|
|
|
const NetEvent *evt = evwt->event(0);
|
2017-12-27 23:41:43 +01:00
|
|
|
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());
|
|
|
|
|
}
|
2017-12-27 23:49:15 +01:00
|
|
|
// Get the NexusSet for the expression.
|
2017-12-27 23:41:43 +01:00
|
|
|
NexusSet *ns_expr = expr->nex_input();
|
2017-12-27 23:49:15 +01:00
|
|
|
// Make sure the event and expression NexusSets match exactly.
|
2017-12-27 23:41:43 +01:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-06 09:21:24 +01:00
|
|
|
DelayType NetWhile::delay_type(bool print_delay) const
|
2008-04-22 20:32:10 +02:00
|
|
|
{
|
2017-12-27 23:41:43 +01:00
|
|
|
// 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;
|
|
|
|
|
}
|
2017-12-06 09:21:24 +01:00
|
|
|
return get_loop_delay_type(cond_, proc_, print_delay);
|
2008-04-22 20:32:10 +02:00
|
|
|
}
|
2017-12-27 23:41:43 +01:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* 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;
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-28 08:07:29 +01:00
|
|
|
// FIXME: User function calls still need to be checked (NetEUFunc).
|
|
|
|
|
// : Non-constant system functions need a warning (NetESFunc).
|
|
|
|
|
// : Constant functions should already be elaborated.
|
|
|
|
|
|
2017-12-27 23:41:43 +01:00
|
|
|
/* 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:
|
2023-04-13 22:00:34 +02:00
|
|
|
ivl_assert(*this, 0);
|
2017-12-27 23:41:43 +01:00
|
|
|
}
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-20 08:21:12 +01:00
|
|
|
bool NetEvNBTrig::check_synth(ivl_process_type_t pr_type,
|
|
|
|
|
const NetScope* /* scope */ ) const
|
|
|
|
|
{
|
|
|
|
|
print_synth_warning(this, "A non-blocking event trigger", pr_type);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-27 23:41:43 +01:00
|
|
|
// 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);
|
|
|
|
|
|
2024-01-07 14:14:48 +01:00
|
|
|
if (!lsig) {
|
|
|
|
|
const NetESelect*lsel = dynamic_cast<const NetESelect*>(left);
|
|
|
|
|
if (lsel && (lsel->expr_width() >= lsel->sub_expr()->expr_width()))
|
|
|
|
|
lsig = dynamic_cast<const NetESignal*>(lsel->sub_expr());
|
|
|
|
|
}
|
|
|
|
|
if (!rsig) {
|
|
|
|
|
const NetESelect*rsel = dynamic_cast<const NetESelect*>(right);
|
|
|
|
|
if (rsel && (rsel->expr_width() >= rsel->sub_expr()->expr_width()))
|
|
|
|
|
rsig = dynamic_cast<const NetESignal*>(rsel->sub_expr());
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-27 23:41:43 +01:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool NetForLoop::check_synth(ivl_process_type_t pr_type,
|
|
|
|
|
const NetScope* scope) const
|
|
|
|
|
{
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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 false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool NetRelease::check_synth(ivl_process_type_t pr_type,
|
|
|
|
|
const NetScope* /* scope */ ) const
|
|
|
|
|
{
|
|
|
|
|
print_synth_warning(this, "A release", pr_type);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool NetRepeat::check_synth(ivl_process_type_t pr_type,
|
|
|
|
|
const NetScope* scope) const
|
|
|
|
|
{
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-28 08:07:29 +01:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-27 17:56:30 +01:00
|
|
|
/*
|
|
|
|
|
* This function is called to make sure the task/function can be used
|
|
|
|
|
* in a context where it must be synthesizable, such as in an always_comb
|
|
|
|
|
* or always_ff.
|
|
|
|
|
*
|
|
|
|
|
* If this is a function, then the function must be void.
|
|
|
|
|
*/
|
|
|
|
|
bool NetBaseDef::check_synth(ivl_process_type_t pr_type,
|
2017-12-28 17:49:12 +01:00
|
|
|
const NetScope* /* scope */) const
|
2017-12-28 08:07:29 +01:00
|
|
|
{
|
2017-12-28 17:49:12 +01:00
|
|
|
bool result = false;
|
2017-12-28 08:07:29 +01:00
|
|
|
const NetScope *tscope = this->scope();
|
2017-12-28 17:49:12 +01:00
|
|
|
result |= tscope->check_synth(pr_type, tscope);
|
2017-12-28 08:07:29 +01:00
|
|
|
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;
|
|
|
|
|
}
|
2017-12-28 17:49:12 +01:00
|
|
|
if (proc_) result |= proc_->check_synth(pr_type, tscope);
|
|
|
|
|
return result;
|
2017-12-28 08:07:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool NetUTask::check_synth(ivl_process_type_t pr_type,
|
|
|
|
|
const NetScope* scope) const
|
|
|
|
|
{
|
2022-02-27 17:56:30 +01:00
|
|
|
const NetScope* task_scope = task();
|
|
|
|
|
if (task_scope->type() == NetScope::FUNC) {
|
|
|
|
|
// This can happen if this a void function.
|
|
|
|
|
return task_scope->func_def()->check_synth(pr_type, scope);
|
|
|
|
|
} else {
|
|
|
|
|
return task_scope->task_def()->check_synth(pr_type, scope);
|
|
|
|
|
}
|
2017-12-28 08:07:29 +01:00
|
|
|
}
|
2017-12-27 23:41:43 +01:00
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|