diff --git a/link_const.cc b/link_const.cc index 051718aaf..d5b77a6a8 100644 --- a/link_const.cc +++ b/link_const.cc @@ -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(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(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(cur->get_obj()))) { @@ -212,6 +225,18 @@ verinum Nexus::driven_vector() const val = obj->value(); width = val.len(); + } else if ((ps = dynamic_cast(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(cur->get_obj()))) { width = sig->vector_width(); diff --git a/synth2.cc b/synth2.cc index 696025240..1c4070db4 100644 --- a/synth2.cc +++ b/synth2.cc @@ -413,22 +413,26 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope, tmp->local_flag(true); tmp->set_line(*this); - NetNet*use_lsig = nex_out.pin(ptr).nexus()->pick_any_net(); - if (use_lsig) { + NetNet*isig = nex_out.pin(ptr).nexus()->pick_any_net(); + if (isig) { if (debug_synth2) { cerr << get_fileline() << ": NetAssignBase::synth_async: " - << " Found a use_sig:" << endl; + << " Found an isig:" << endl; nex_out.pin(ptr).dump_link(cerr, 8); } } else { if (debug_synth2) { cerr << get_fileline() << ": NetAssignBase::synth_async: " - << " Found no use_sig, resorting to lsig." << endl; + << " Found no isig, resorting to lsig." << endl; } - use_lsig = lsig; + isig = new NetNet(scope, scope->local_symbol(), + NetNet::WIRE, NetNet::not_an_array, tmp_type); + isig->local_flag(true); + isig->set_line(*this); + connect(isig->pin(0), nex_out.pin(ptr)); } - ivl_assert(*this, use_lsig); - NetSubstitute*ps = new NetSubstitute(use_lsig, rsig, lsig_width, base_off); + ivl_assert(*this, isig); + NetSubstitute*ps = new NetSubstitute(isig, rsig, lsig_width, base_off); ps->set_line(*this); des->add_node(ps); @@ -1766,10 +1770,19 @@ bool NetCondit::synth_sync(Design*des, NetScope*scope, for (unsigned pin = 0 ; pin < tmp_out.pin_count() ; pin += 1) { Nexus*rst_nex = tmp_out.pin(pin).nexus(); + if (!all_bits_driven(tmp_masks[pin])) { + cerr << get_fileline() << ": sorry: Not all bits of '" + << nex_map[idx].lnk.nexus()->pick_any_net()->name() + << "' are asynchronously set or reset. This is " + << "not currently supported in synthesis." << endl; + des->errors += 1; + return false; + } + if (! rst_nex->drivers_constant() || ! tmp_ena.pin(pin).is_linked(scope->tie_hi()) ) { - cerr << get_fileline() << ": sorry: " - << "Asynchronous LOAD not implemented." << endl; + cerr << get_fileline() << ": sorry: Asynchronous load " + << "is not currently supported in synthesis." << endl; des->errors += 1; return false; } @@ -1777,7 +1790,7 @@ bool NetCondit::synth_sync(Design*des, NetScope*scope, if (ff_aclr.pin(pin).is_linked() || ff_aset.pin(pin).is_linked()) { cerr << get_fileline() << ": sorry: More than " - "one asynchronous set/reset signal is " + "one asynchronous set/reset clause is " "not currently supported in synthesis." << endl; des->errors += 1; return false;