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

This commit is contained in:
Stephen Williams 2016-02-22 09:49:28 -08:00
commit bc23bc71e3
8 changed files with 1062 additions and 720 deletions

View File

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

View File

@ -369,6 +369,7 @@ NetEvWait::~NetEvWait()
tmp->next = tmp->next->next;
delete tmp;
}
delete tgt;
}
events_.clear();
}

View File

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

View File

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

View File

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

View File

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

1568
synth2.cc

File diff suppressed because it is too large Load Diff

View File

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