Merge branch 'master' of github.com:steveicarus/iverilog
This commit is contained in:
commit
bc23bc71e3
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2000-2015 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2016 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -102,6 +102,17 @@ bool Nexus::drivers_constant() const
|
|||
break;
|
||||
}
|
||||
|
||||
const NetSubstitute*ps = dynamic_cast<const NetSubstitute*>(cur->get_obj());
|
||||
if (ps) {
|
||||
if (ps->pin(1).nexus()->drivers_constant() &&
|
||||
ps->pin(2).nexus()->drivers_constant() ) {
|
||||
constant_drivers += 1;
|
||||
continue;
|
||||
}
|
||||
driven_ = VAR;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! dynamic_cast<const NetConst*>(cur->get_obj())) {
|
||||
driven_ = VAR;
|
||||
return false;
|
||||
|
|
@ -199,10 +210,12 @@ verinum Nexus::driven_vector() const
|
|||
const Link*cur = list_;
|
||||
|
||||
verinum val;
|
||||
verinum pval;
|
||||
unsigned width = 0;
|
||||
|
||||
for (cur = first_nlink() ; cur ; cur = cur->next_nlink()) {
|
||||
|
||||
const NetSubstitute*ps;
|
||||
const NetConst*obj;
|
||||
const NetNet*sig;
|
||||
if ((obj = dynamic_cast<const NetConst*>(cur->get_obj()))) {
|
||||
|
|
@ -212,6 +225,18 @@ verinum Nexus::driven_vector() const
|
|||
val = obj->value();
|
||||
width = val.len();
|
||||
|
||||
} else if ((ps = dynamic_cast<const NetSubstitute*>(cur->get_obj()))) {
|
||||
if (cur->get_pin() != 0)
|
||||
continue;
|
||||
|
||||
// Multiple drivers are not currently supported.
|
||||
ivl_assert(*ps, val.len() == 0);
|
||||
val = ps->pin(1).nexus()->driven_vector();
|
||||
pval = ps->pin(2).nexus()->driven_vector();
|
||||
for (unsigned idx = 0; idx < pval.len(); idx += 1)
|
||||
val.set(ps->base() + idx, pval.get(idx));
|
||||
width = val.len();
|
||||
|
||||
} else if ((sig = dynamic_cast<const NetNet*>(cur->get_obj()))) {
|
||||
|
||||
width = sig->vector_width();
|
||||
|
|
|
|||
|
|
@ -369,6 +369,7 @@ NetEvWait::~NetEvWait()
|
|||
tmp->next = tmp->next->next;
|
||||
delete tmp;
|
||||
}
|
||||
delete tgt;
|
||||
}
|
||||
events_.clear();
|
||||
}
|
||||
|
|
|
|||
27
net_link.cc
27
net_link.cc
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2000-2013 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2016 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -311,6 +311,20 @@ void Nexus::count_io(unsigned&inp, unsigned&out) const
|
|||
}
|
||||
}
|
||||
|
||||
bool Nexus::has_floating_input() const
|
||||
{
|
||||
bool found_input = false;
|
||||
for (const Link*cur = first_nlink() ; cur ; cur = cur->next_nlink()) {
|
||||
if (cur->get_dir() == Link::OUTPUT)
|
||||
return false;
|
||||
|
||||
if (cur->get_dir() == Link::INPUT)
|
||||
found_input = true;
|
||||
}
|
||||
|
||||
return found_input;
|
||||
}
|
||||
|
||||
bool Nexus::drivers_present() const
|
||||
{
|
||||
for (const Link*cur = first_nlink() ; cur ; cur = cur->next_nlink()) {
|
||||
|
|
@ -467,6 +481,17 @@ NetNet* Nexus::pick_any_net()
|
|||
return 0;
|
||||
}
|
||||
|
||||
NetNode* Nexus::pick_any_node()
|
||||
{
|
||||
for (Link*cur = first_nlink() ; cur ; cur = cur->next_nlink()) {
|
||||
NetNode*node = dynamic_cast<NetNode*>(cur->get_obj());
|
||||
if (node != 0)
|
||||
return node;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char* Nexus::name() const
|
||||
{
|
||||
if (name_)
|
||||
|
|
|
|||
35
net_scope.cc
35
net_scope.cc
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2016 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -23,6 +23,7 @@
|
|||
# include "netlist.h"
|
||||
# include "netclass.h"
|
||||
# include "netenum.h"
|
||||
# include "netvector.h"
|
||||
# include <cstring>
|
||||
# include <cstdlib>
|
||||
# include <sstream>
|
||||
|
|
@ -161,6 +162,8 @@ NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t, bool nest,
|
|||
lineno_ = 0;
|
||||
def_lineno_ = 0;
|
||||
genvar_tmp_val = 0;
|
||||
tie_hi_ = 0;
|
||||
tie_lo_ = 0;
|
||||
}
|
||||
|
||||
NetScope::~NetScope()
|
||||
|
|
@ -744,3 +747,33 @@ perm_string NetScope::local_symbol()
|
|||
res << "_s" << (lcounter_++);
|
||||
return lex_strings.make(res.str());
|
||||
}
|
||||
|
||||
void NetScope::add_tie_hi(Design*des)
|
||||
{
|
||||
if (tie_hi_ == 0) {
|
||||
NetNet*sig = new NetNet(this, lex_strings.make("_LOGIC1"),
|
||||
NetNet::WIRE, &netvector_t::scalar_logic);
|
||||
sig->local_flag(true);
|
||||
|
||||
tie_hi_ = new NetLogic(this, local_symbol(),
|
||||
1, NetLogic::PULLUP, 1);
|
||||
des->add_node(tie_hi_);
|
||||
|
||||
connect(sig->pin(0), tie_hi_->pin(0));
|
||||
}
|
||||
}
|
||||
|
||||
void NetScope::add_tie_lo(Design*des)
|
||||
{
|
||||
if (tie_lo_ == 0) {
|
||||
NetNet*sig = new NetNet(this, lex_strings.make("_LOGIC0"),
|
||||
NetNet::WIRE, &netvector_t::scalar_logic);
|
||||
sig->local_flag(true);
|
||||
|
||||
tie_lo_ = new NetLogic(this, local_symbol(),
|
||||
1, NetLogic::PULLDOWN, 1);
|
||||
des->add_node(tie_lo_);
|
||||
|
||||
connect(sig->pin(0), tie_lo_->pin(0));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
27
netlist.cc
27
netlist.cc
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1998-2015 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2016 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -1022,11 +1022,36 @@ NetProc::~NetProc()
|
|||
NetProcTop::NetProcTop(NetScope*s, ivl_process_type_t t, NetProc*st)
|
||||
: type_(t), statement_(st), scope_(s)
|
||||
{
|
||||
synthesized_design_ = 0;
|
||||
}
|
||||
|
||||
NetProcTop::~NetProcTop()
|
||||
{
|
||||
if (!synthesized_design_) {
|
||||
delete statement_;
|
||||
return;
|
||||
}
|
||||
|
||||
NexusSet nex_set;
|
||||
statement_->nex_output(nex_set);
|
||||
|
||||
delete statement_;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
NetProc* NetProcTop::statement()
|
||||
|
|
|
|||
89
netlist.h
89
netlist.h
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef IVL_netlist_H
|
||||
#define IVL_netlist_H
|
||||
/*
|
||||
* Copyright (c) 1998-2015 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2016 Stephen Williams (steve@icarus.com)
|
||||
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
|
|
@ -379,6 +379,8 @@ class Nexus {
|
|||
|
||||
NetNet* pick_any_net();
|
||||
|
||||
NetNode* pick_any_node();
|
||||
|
||||
/* This method counts the number of input and output links for
|
||||
this nexus, and assigns the results to the output arguments. */
|
||||
void count_io(unsigned&inp, unsigned&out) const;
|
||||
|
|
@ -388,6 +390,10 @@ class Nexus {
|
|||
is a variable, but also if this is a net with a force. */
|
||||
bool assign_lval() const;
|
||||
|
||||
/* This method returns true if there are any inputs
|
||||
attached to this nexus but no drivers. */
|
||||
bool has_floating_input() const;
|
||||
|
||||
/* This method returns true if there are any drivers
|
||||
(including variables) attached to this nexus. */
|
||||
bool drivers_present() const;
|
||||
|
|
@ -1146,6 +1152,12 @@ class NetScope : public Definitions, public Attrib {
|
|||
children of this node as well. */
|
||||
void run_functor(Design*des, functor_t*fun);
|
||||
|
||||
/* These are used in synthesis. They provide shared pullup and
|
||||
pulldown nodes for this scope. */
|
||||
void add_tie_hi(Design*des);
|
||||
void add_tie_lo(Design*des);
|
||||
Link&tie_hi() const { return tie_hi_->pin(0); };
|
||||
Link&tie_lo() const { return tie_lo_->pin(0); };
|
||||
|
||||
/* This member is used during elaboration to pass defparam
|
||||
assignments from the scope pass to the parameter evaluation
|
||||
|
|
@ -1267,6 +1279,9 @@ class NetScope : public Definitions, public Attrib {
|
|||
/* Final procedures sets this to notify statements that
|
||||
they are part of a final procedure. */
|
||||
bool in_final_;
|
||||
|
||||
NetNode*tie_hi_;
|
||||
NetNode*tie_lo_;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -2603,33 +2618,48 @@ class NetProc : public virtual LineInfo {
|
|||
// process. Most process types are not.
|
||||
virtual bool is_synchronous();
|
||||
|
||||
// Synthesize as asynchronous logic, and return true. The
|
||||
// nex_out is where this function attaches its output
|
||||
// results. The accumulated_nex_out is used by sequential
|
||||
// blocks to show outputs from the previous code.
|
||||
// Synthesize as asynchronous logic, and return true on success.
|
||||
//
|
||||
// nex_map holds the set of nexuses that are driven by this
|
||||
// process, nex_out holds the accumulated outputs from this and
|
||||
// preceeding sequential processes (i.e statements in the same
|
||||
// block), enables holds the accumulated clock/gate enables,
|
||||
// and bitmasks holds the accumulated masks that flag which bits
|
||||
// are unconditionally driven (i.e. driven by every clause in
|
||||
// every statement). On output, the values passed in to nex_out,
|
||||
// enables, and bitmasks may either be merged with or replaced
|
||||
// by the values originating from this process, depending on the
|
||||
// type of statement this process represents.
|
||||
//
|
||||
// The clock/gate enables generated by synthesis operate at a
|
||||
// vector level (i.e. they are asserted if any bit(s) in the
|
||||
// vector are driven).
|
||||
typedef vector<bool> mask_t;
|
||||
virtual bool synth_async(Design*des, NetScope*scope,
|
||||
NexusSet&nex_map,
|
||||
NetBus&nex_out,
|
||||
NetBus&accumulated_nex_out);
|
||||
NexusSet&nex_map, NetBus&nex_out,
|
||||
NetBus&enables, vector<mask_t>&bitmasks);
|
||||
|
||||
// Synthesize as synchronous logic, and return true. That
|
||||
// means binding the outputs to the data port of a FF, and the
|
||||
// event inputs to a FF clock. Only some key NetProc sub-types
|
||||
// Synthesize as synchronous logic, and return true on success.
|
||||
// That means binding the outputs to the data port of a FF, and
|
||||
// the event inputs to a FF clock. Only some key NetProc sub-types
|
||||
// that have specific meaning in synchronous statements. The
|
||||
// remainder reduce to a call to synth_async that connects the
|
||||
// output to the Data input of the FF.
|
||||
//
|
||||
// The events argument is filled in be the NetEvWait
|
||||
// implementation of this method with the probes that it does
|
||||
// not itself pick off as a clock. These events should be
|
||||
// picked off by e.g. condit statements as set/reset inputs to
|
||||
// the flipflop being generated.
|
||||
// The nex_map, nex_out, ff_ce, and bitmasks arguments serve
|
||||
// the same purpose as in the synth_async method (where ff_ce
|
||||
// is equivalent to enables). The events argument is filled
|
||||
// in by the NetEvWait implementation of this method with the
|
||||
// probes that it does not itself pick off as a clock. These
|
||||
// events should be picked off by e.g. condit statements as
|
||||
// asynchronous set/reset inputs to the flipflop being generated.
|
||||
virtual bool synth_sync(Design*des, NetScope*scope,
|
||||
bool&ff_negedge,
|
||||
NetNet*ff_clock, NetBus&ff_ce,
|
||||
NetBus&ff_aclr, NetBus&ff_aset,
|
||||
vector<verinum>&ff_aset_value,
|
||||
NexusSet&nex_map, NetBus&nex_out,
|
||||
vector<mask_t>&bitmasks,
|
||||
const std::vector<NetEvProbe*>&events);
|
||||
|
||||
virtual void dump(ostream&, unsigned ind) const;
|
||||
|
|
@ -2640,7 +2670,9 @@ class NetProc : public virtual LineInfo {
|
|||
protected:
|
||||
bool synth_async_block_substatement_(Design*des, NetScope*scope,
|
||||
NexusSet&nex_map,
|
||||
NetBus&accumulated_nex_out,
|
||||
NetBus&nex_out,
|
||||
NetBus&enables,
|
||||
vector<mask_t>&bitmasks,
|
||||
NetProc*substmt);
|
||||
private:
|
||||
friend class NetBlock;
|
||||
|
|
@ -2819,7 +2851,7 @@ class NetAssignBase : public NetProc {
|
|||
|
||||
bool synth_async(Design*des, NetScope*scope,
|
||||
NexusSet&nex_map, NetBus&nex_out,
|
||||
NetBus&accumulated_nex_out);
|
||||
NetBus&enables, vector<mask_t>&bitmasks);
|
||||
|
||||
// This dumps all the lval structures.
|
||||
void dump_lval(ostream&) const;
|
||||
|
|
@ -2905,7 +2937,7 @@ class NetBlock : public NetProc {
|
|||
// synthesize as asynchronous logic, and return true.
|
||||
bool synth_async(Design*des, NetScope*scope,
|
||||
NexusSet&nex_map, NetBus&nex_out,
|
||||
NetBus&accumulated_nex_out);
|
||||
NetBus&enables, vector<mask_t>&bitmasks);
|
||||
|
||||
bool synth_sync(Design*des, NetScope*scope,
|
||||
bool&ff_negedge,
|
||||
|
|
@ -2913,6 +2945,7 @@ class NetBlock : public NetProc {
|
|||
NetBus&ff_aclr,NetBus&ff_aset,
|
||||
vector<verinum>&ff_aset_value,
|
||||
NexusSet&nex_map, NetBus&nex_out,
|
||||
vector<mask_t>&bitmasks,
|
||||
const std::vector<NetEvProbe*>&events);
|
||||
|
||||
// This version of emit_recurse scans all the statements of
|
||||
|
|
@ -2968,7 +3001,7 @@ class NetCase : public NetProc {
|
|||
|
||||
bool synth_async(Design*des, NetScope*scope,
|
||||
NexusSet&nex_map, NetBus&nex_out,
|
||||
NetBus&accumulated_nex_out);
|
||||
NetBus&enables, vector<mask_t>&bitmasks);
|
||||
|
||||
virtual bool emit_proc(struct target_t*) const;
|
||||
virtual void dump(ostream&, unsigned ind) const;
|
||||
|
|
@ -2984,7 +3017,7 @@ class NetCase : public NetProc {
|
|||
|
||||
bool synth_async_casez_(Design*des, NetScope*scope,
|
||||
NexusSet&nex_map, NetBus&nex_out,
|
||||
NetBus&accumulated_nex_out);
|
||||
NetBus&enables, vector<mask_t>&bitmasks);
|
||||
|
||||
TYPE type_;
|
||||
|
||||
|
|
@ -3048,7 +3081,7 @@ class NetCondit : public NetProc {
|
|||
bool is_asynchronous();
|
||||
bool synth_async(Design*des, NetScope*scope,
|
||||
NexusSet&nex_map, NetBus&nex_out,
|
||||
NetBus&accumulated_nex_out);
|
||||
NetBus&enables, vector<mask_t>&bitmasks);
|
||||
|
||||
bool synth_sync(Design*des, NetScope*scope,
|
||||
bool&ff_negedge,
|
||||
|
|
@ -3056,6 +3089,7 @@ class NetCondit : public NetProc {
|
|||
NetBus&ff_aclr,NetBus&ff_aset,
|
||||
vector<verinum>&ff_aset_value,
|
||||
NexusSet&nex_map, NetBus&nex_out,
|
||||
vector<mask_t>&bitmasks,
|
||||
const std::vector<NetEvProbe*>&events);
|
||||
|
||||
virtual bool emit_proc(struct target_t*) const;
|
||||
|
|
@ -3327,7 +3361,7 @@ class NetEvWait : public NetProc {
|
|||
|
||||
virtual bool synth_async(Design*des, NetScope*scope,
|
||||
NexusSet&nex_map, NetBus&nex_out,
|
||||
NetBus&accumulated_nex_out);
|
||||
NetBus&enables, vector<mask_t>&bitmasks);
|
||||
|
||||
virtual bool synth_sync(Design*des, NetScope*scope,
|
||||
bool&ff_negedge,
|
||||
|
|
@ -3335,6 +3369,7 @@ class NetEvWait : public NetProc {
|
|||
NetBus&ff_aclr,NetBus&ff_aset,
|
||||
vector<verinum>&ff_aset_value,
|
||||
NexusSet&nex_map, NetBus&nex_out,
|
||||
vector<mask_t>&bitmasks,
|
||||
const std::vector<NetEvProbe*>&events);
|
||||
|
||||
virtual void dump(ostream&, unsigned ind) const;
|
||||
|
|
@ -3439,7 +3474,7 @@ class NetForLoop : public NetProc {
|
|||
// synthesize as asynchronous logic, and return true.
|
||||
bool synth_async(Design*des, NetScope*scope,
|
||||
NexusSet&nex_map, NetBus&nex_out,
|
||||
NetBus&accumulated_nex_out);
|
||||
NetBus&enables, vector<mask_t>&bitmasks);
|
||||
|
||||
private:
|
||||
NetNet*index_;
|
||||
|
|
@ -3827,8 +3862,14 @@ class NetProcTop : public LineInfo, public Attrib {
|
|||
bool emit(struct target_t*tgt) const;
|
||||
|
||||
private:
|
||||
bool tie_off_floating_inputs_(Design*des,
|
||||
NexusSet&nex_map, NetBus&nex_in,
|
||||
vector<NetProc::mask_t>&bitmasks,
|
||||
bool is_ff_input);
|
||||
|
||||
const ivl_process_type_t type_;
|
||||
NetProc*const statement_;
|
||||
Design*synthesized_design_;
|
||||
|
||||
NetScope*scope_;
|
||||
friend class Design;
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ void vvp_dff::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
|
|||
tmp = clk_;
|
||||
clk_ = bit.value(0);
|
||||
if (clk_ == clk_active_ && tmp != clk_active_)
|
||||
port.ptr()->send_vec4(d_, 0);
|
||||
schedule_propagate_vector(port.ptr(), 0, d_);
|
||||
break;
|
||||
|
||||
case 2: // CE
|
||||
|
|
@ -118,17 +118,17 @@ void vvp_dff::recv_async(vvp_net_ptr_t)
|
|||
|
||||
void vvp_dff_aclr::recv_async(vvp_net_ptr_t port)
|
||||
{
|
||||
port.ptr()->send_vec4(vvp_vector4_t(d_.size(), BIT4_0), 0);
|
||||
schedule_propagate_vector(port.ptr(), 0, vvp_vector4_t(d_.size(), BIT4_0));
|
||||
}
|
||||
|
||||
void vvp_dff_aset::recv_async(vvp_net_ptr_t port)
|
||||
{
|
||||
port.ptr()->send_vec4(vvp_vector4_t(d_.size(), BIT4_1), 0);
|
||||
schedule_propagate_vector(port.ptr(), 0, vvp_vector4_t(d_.size(), BIT4_1));
|
||||
}
|
||||
|
||||
void vvp_dff_asc::recv_async(vvp_net_ptr_t port)
|
||||
{
|
||||
port.ptr()->send_vec4(asc_value_, 0);
|
||||
schedule_propagate_vector(port.ptr(), 0, asc_value_);
|
||||
}
|
||||
|
||||
void compile_dff(char*label, unsigned width, bool negedge,
|
||||
|
|
|
|||
Loading…
Reference in New Issue