Enhanced support for asynchronous set/reset in synthesis.

Added the ability to coalesce set/reset values to different parts
of the same vector. Also added a check that all bits of the vector
are assigned a value.
Enabled coalescence of asynchronous set/reset part-vectors
This commit is contained in:
Martin Whitaker 2016-02-21 21:46:36 +00:00
parent 3fc0204b99
commit f29935d8dd
2 changed files with 49 additions and 11 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

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