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:
parent
3fc0204b99
commit
f29935d8dd
|
|
@ -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
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
|
@ -102,6 +102,17 @@ bool Nexus::drivers_constant() const
|
||||||
break;
|
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())) {
|
if (! dynamic_cast<const NetConst*>(cur->get_obj())) {
|
||||||
driven_ = VAR;
|
driven_ = VAR;
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -199,10 +210,12 @@ verinum Nexus::driven_vector() const
|
||||||
const Link*cur = list_;
|
const Link*cur = list_;
|
||||||
|
|
||||||
verinum val;
|
verinum val;
|
||||||
|
verinum pval;
|
||||||
unsigned width = 0;
|
unsigned width = 0;
|
||||||
|
|
||||||
for (cur = first_nlink() ; cur ; cur = cur->next_nlink()) {
|
for (cur = first_nlink() ; cur ; cur = cur->next_nlink()) {
|
||||||
|
|
||||||
|
const NetSubstitute*ps;
|
||||||
const NetConst*obj;
|
const NetConst*obj;
|
||||||
const NetNet*sig;
|
const NetNet*sig;
|
||||||
if ((obj = dynamic_cast<const NetConst*>(cur->get_obj()))) {
|
if ((obj = dynamic_cast<const NetConst*>(cur->get_obj()))) {
|
||||||
|
|
@ -212,6 +225,18 @@ verinum Nexus::driven_vector() const
|
||||||
val = obj->value();
|
val = obj->value();
|
||||||
width = val.len();
|
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()))) {
|
} else if ((sig = dynamic_cast<const NetNet*>(cur->get_obj()))) {
|
||||||
|
|
||||||
width = sig->vector_width();
|
width = sig->vector_width();
|
||||||
|
|
|
||||||
33
synth2.cc
33
synth2.cc
|
|
@ -413,22 +413,26 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope,
|
||||||
tmp->local_flag(true);
|
tmp->local_flag(true);
|
||||||
tmp->set_line(*this);
|
tmp->set_line(*this);
|
||||||
|
|
||||||
NetNet*use_lsig = nex_out.pin(ptr).nexus()->pick_any_net();
|
NetNet*isig = nex_out.pin(ptr).nexus()->pick_any_net();
|
||||||
if (use_lsig) {
|
if (isig) {
|
||||||
if (debug_synth2) {
|
if (debug_synth2) {
|
||||||
cerr << get_fileline() << ": NetAssignBase::synth_async: "
|
cerr << get_fileline() << ": NetAssignBase::synth_async: "
|
||||||
<< " Found a use_sig:" << endl;
|
<< " Found an isig:" << endl;
|
||||||
nex_out.pin(ptr).dump_link(cerr, 8);
|
nex_out.pin(ptr).dump_link(cerr, 8);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (debug_synth2) {
|
if (debug_synth2) {
|
||||||
cerr << get_fileline() << ": NetAssignBase::synth_async: "
|
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);
|
ivl_assert(*this, isig);
|
||||||
NetSubstitute*ps = new NetSubstitute(use_lsig, rsig, lsig_width, base_off);
|
NetSubstitute*ps = new NetSubstitute(isig, rsig, lsig_width, base_off);
|
||||||
ps->set_line(*this);
|
ps->set_line(*this);
|
||||||
des->add_node(ps);
|
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) {
|
for (unsigned pin = 0 ; pin < tmp_out.pin_count() ; pin += 1) {
|
||||||
Nexus*rst_nex = tmp_out.pin(pin).nexus();
|
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() ||
|
if (! rst_nex->drivers_constant() ||
|
||||||
! tmp_ena.pin(pin).is_linked(scope->tie_hi()) ) {
|
! tmp_ena.pin(pin).is_linked(scope->tie_hi()) ) {
|
||||||
cerr << get_fileline() << ": sorry: "
|
cerr << get_fileline() << ": sorry: Asynchronous load "
|
||||||
<< "Asynchronous LOAD not implemented." << endl;
|
<< "is not currently supported in synthesis." << endl;
|
||||||
des->errors += 1;
|
des->errors += 1;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -1777,7 +1790,7 @@ bool NetCondit::synth_sync(Design*des, NetScope*scope,
|
||||||
if (ff_aclr.pin(pin).is_linked() ||
|
if (ff_aclr.pin(pin).is_linked() ||
|
||||||
ff_aset.pin(pin).is_linked()) {
|
ff_aset.pin(pin).is_linked()) {
|
||||||
cerr << get_fileline() << ": sorry: More than "
|
cerr << get_fileline() << ": sorry: More than "
|
||||||
"one asynchronous set/reset signal is "
|
"one asynchronous set/reset clause is "
|
||||||
"not currently supported in synthesis." << endl;
|
"not currently supported in synthesis." << endl;
|
||||||
des->errors += 1;
|
des->errors += 1;
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue