Fixed dangling latch gate inputs.

With -tfnf, observed
(latch  43020 1 43022 43021)
in the output file. That 3rd number is the ID of the gate nexus. However, it was only found as
(dangle 43022)
The purpose of this patch is to fix that in the common code.
This commit is contained in:
Alan M. Feldstein 2007-10-23 12:01:39 -05:00 committed by Stephen Williams
parent f600e774d5
commit 5cae6b64af
10 changed files with 13713 additions and 5 deletions

View File

@ -3,6 +3,7 @@
// Class NetLatch member-function definitions
#include "NetLatch.h" // NetLatch class definition
#include "target.h" // target_t structure definition
// constructor
NetLatch::NetLatch( NetScope *scope, perm_string name, unsigned width )
@ -11,6 +12,11 @@ NetLatch::NetLatch( NetScope *scope, perm_string name, unsigned width )
{
} // end NetLatch constructor
unsigned NetLatch::width() const
{
return ( pin_count() - 1U ) / 2U;
} // end function width
Link &NetLatch::pin_Data( unsigned w )
{
unsigned pn = 1 + 2 * w;
@ -28,4 +34,15 @@ Link &NetLatch::pin_Q( unsigned w )
Link &NetLatch::pin_Gate()
{
return pin( 0 );
} // end function pin_Q
} // end function pin_Gate
const Link &NetLatch::pin_Gate() const
{
return pin( 0 );
} // end function pin_Gate
bool NetLatch::emit_node( target_t *driverPtr ) const
{
driverPtr->lpm_latch( this );
return true;
} // end function emit_node

View File

@ -18,6 +18,8 @@ class NetLatch : public NetNode
public:
NetLatch( NetScope *, perm_string, unsigned );
unsigned width() const;
Link &pin_Data( unsigned );
Link &pin_Q( unsigned );
Link &pin_Gate();
@ -25,6 +27,8 @@ class NetLatch : public NetNode
const Link &pin_Data( unsigned ) const;
const Link &pin_Q( unsigned ) const;
const Link &pin_Gate() const;
virtual bool emit_node( target_t * ) const;
}; // end class NetLatch
#endif

13590
UML.mdxml Normal file

File diff suppressed because one or more lines are too long

View File

@ -230,6 +230,7 @@ typedef enum ivl_lpm_type_e {
IVL_LPM_DEMUX = 16,
IVL_LPM_DIVIDE = 12,
IVL_LPM_FF = 3,
IVL_LPM_LATCH = 17,
IVL_LPM_MOD = 13,
IVL_LPM_MULT = 4,
IVL_LPM_MUX = 5,
@ -749,6 +750,8 @@ extern ivl_nexus_t ivl_lpm_sync_set(ivl_lpm_t net);
extern ivl_expr_t ivl_lpm_sset_value(ivl_lpm_t net);
/* IVL_LPM_FF IVL_LPM_RAM */
extern ivl_nexus_t ivl_lpm_clk(ivl_lpm_t net);
/* IVL_LPM_LATCH */
extern ivl_nexus_t ivl_lpm_gate( ivl_lpm_t netPtr );
/* IVL_LPM_FF */
extern ivl_lpm_t ivl_lpm_decode(ivl_lpm_t net);
/* IVL_LPM_UFUNC */
@ -756,7 +759,7 @@ extern ivl_scope_t ivl_lpm_define(ivl_lpm_t net);
/* IVL_LPM_FF IVL_LPM_RAM */
extern ivl_nexus_t ivl_lpm_enable(ivl_lpm_t net);
/* IVL_LPM_ADD IVL_LPM_DEMUX IVL_LPM_FF IVL_LPM_MULT */
/* IVL_LPM_RAM IVL_LPM_SUB */
/* IVL_LPM_RAM IVL_LPM_SUB IVL_LPM_LATCH */
extern ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx);
/* IVL_LPM_ADD IVL_LPM_DEMUX IVL_LPM_MULT IVL_LPM_SUB */
/* IVL_LPM_MUX IVL_LPM_UFUNC */
@ -765,7 +768,7 @@ extern ivl_nexus_t ivl_lpm_data2(ivl_lpm_t net, unsigned sdx, unsigned idx);
/* IVL_LPM_UFUNC */
extern unsigned ivl_lpm_data2_width(ivl_lpm_t net, unsigned sdx);
/* IVL_LPM_ADD IVL_LPM_DEMUX IVL_LPM_FF IVL_LPM_MULT IVL_LPM_RAM IVL_LPM_SUB
IVL_LPM_UFUNC */
IVL_LPM_UFUNC IVL_LPM_LATCH */
extern ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx);
/* IVL_LPM_MUX IVL_LPM_DECODE IVL_LPM_DEMUX IVL_LPM_RAM */
extern unsigned ivl_lpm_selects(ivl_lpm_t net);

View File

@ -231,7 +231,6 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope, bool sync_flag,
}
des->add_node( latchPtr );
delete latchPtr;
}
catch ( bad_alloc &memoryAllocationException )
@ -1083,7 +1082,7 @@ bool NetCase::synth_async_1hot_(Design*des, NetScope*scope, bool sync_flag,
/*
* Handle synthesis for an asynchronous condition statement. If we get
* here, we know that the CE of a DFF has already been filled, so the
* condition expression goes to the select of an asynchronous mux.
* condition expression goes to the select of an asynchronous mux, unless a latch is inferred in which case it goes to the latch's gate input.
*/
bool NetCondit::synth_async(Design*des, NetScope*scope, bool sync_flag,
struct sync_accounting_cell*nex_ff,

View File

@ -28,6 +28,9 @@
# include <malloc.h>
#endif
#include <stdexcept>
using std::invalid_argument;
/* THE FOLLOWING ARE FUNCTIONS THAT ARE CALLED FROM THE TARGET. */
extern "C" const char*ivl_design_flag(ivl_design_t des, const char*key)
@ -481,6 +484,7 @@ extern "C" unsigned long ivl_expr_uvalue(ivl_expr_t net)
default:
assert(0);
return 0UL;
}
}
@ -699,6 +703,21 @@ extern "C" ivl_nexus_t ivl_lpm_clk(ivl_lpm_t net)
}
}
extern "C" ivl_nexus_t ivl_lpm_gate( ivl_lpm_t netPtr )
{
assert( netPtr );
switch ( netPtr->type )
{
case IVL_LPM_LATCH:
return netPtr->u_.latch.gatePtr;
default:
assert( false );
return 0;
}
}
extern "C" ivl_expr_t ivl_lpm_aset_value(ivl_lpm_t net)
{
assert(net);
@ -782,6 +801,20 @@ extern "C" ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx)
else
return net->u_.ff.d.pins[idx];
case IVL_LPM_LATCH:
if( idx >= net->u_.latch.width )
{
throw invalid_argument( "idx too high" );
}
if ( net->u_.latch.width != 1U )
{
throw invalid_argument( "Only 1-wide latches are currently supported." );
}
return net->u_.latch.dataPtr;
default:
assert(0);
return 0;
@ -940,6 +973,20 @@ extern "C" ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx)
else
return net->u_.ff.q.pins[idx];
case IVL_LPM_LATCH:
if ( idx >= net->u_.latch.width )
{
throw invalid_argument( "idx too high" );
}
if ( net->u_.latch.width != 1U )
{
throw invalid_argument( "Only 1-wide latches are currently supported." );
}
return net->u_.latch.qPtr;
case IVL_LPM_MUX:
assert(idx < net->u_.mux.width);
if (net->u_.mux.width == 1)
@ -1084,6 +1131,8 @@ extern "C" unsigned ivl_lpm_width(ivl_lpm_t net)
case IVL_LPM_FF:
case IVL_LPM_RAM:
return net->u_.ff.width;
case IVL_LPM_LATCH:
return net->u_.latch.width;
case IVL_LPM_DECODE:
case IVL_LPM_MUX:
return net->u_.mux.width;

View File

@ -33,6 +33,9 @@
#endif
# include <stdlib.h>
#include <new> // standard operator new
using std::bad_alloc;
#if defined(__WIN32__)
inline ivl_dll_t ivl_dlopen(const char *name)
@ -1734,6 +1737,33 @@ void dll_target::lpm_ff(const NetFF*net)
}
}
void dll_target::lpm_latch( const NetLatch *latchPtr )
{
try
{
ivl_lpm_s *objPtr = new ivl_lpm_s;
objPtr->type = IVL_LPM_LATCH;
objPtr->name = latchPtr->name();
objPtr->scope = find_scope( des_, latchPtr->scope() );
assert( objPtr->scope ); // C++ programmers prefer using exceptions rather than assertions.
objPtr->u_.latch.width = latchPtr->width();
objPtr->nattr = latchPtr->attr_cnt();
objPtr->attr = fill_in_attributes( latchPtr );
scope_add_lpm( objPtr->scope, objPtr );
// Set the gate signal to point to the nexus, and the nexus to point back to this device.
const Nexus *const nexPtr = latchPtr->pin_Gate().nexus();
}
catch ( bad_alloc &memoryAllocationException )
{
cerr << "Exception occurred: " << memoryAllocationException.what() << endl;
}
} // end function lpm_latch
void dll_target::lpm_ram_dq(const NetRamDq*net)
{
ivl_memory_t mem = find_memory(des_, net->mem());

View File

@ -80,6 +80,7 @@ struct dll_target : public target_t, public expr_scan_t {
bool lpm_demux(const NetDemux*);
void lpm_divide(const NetDivide*);
void lpm_ff(const NetFF*);
void lpm_latch( const NetLatch * );
void lpm_modulo(const NetModulo*);
void lpm_mult(const NetMult*);
void lpm_mux(const NetMux*);
@ -328,6 +329,14 @@ struct ivl_lpm_s {
ivl_expr_t sset_value;
} ff;
struct ivl_lpm_latch_s
{
unsigned width;
ivl_nexus_s *gatePtr;
ivl_nexus_s *qPtr;
ivl_nexus_s *dataPtr;
} latch;
struct ivl_lpm_mux_s {
unsigned width;
unsigned size;

View File

@ -133,6 +133,11 @@ void target_t::lpm_ff(const NetFF*)
"Unhandled NetFF." << endl;
}
void target_t::lpm_latch( const NetLatch * )
{
cerr << "target (" << typeid( *this ).name() << "): Unhandled NetLatch." << endl;
}
void target_t::lpm_mult(const NetMult*)
{
cerr << "target (" << typeid(*this).name() << "): "

View File

@ -23,6 +23,7 @@
#endif
# include "netlist.h"
#include "NetLatch.h"
/*
* This header file describes the types and constants used to describe
@ -84,6 +85,7 @@ struct target_t {
virtual void lpm_divide(const NetDivide*);
virtual void lpm_modulo(const NetModulo*);
virtual void lpm_ff(const NetFF*);
virtual void lpm_latch( const NetLatch * );
virtual void lpm_mult(const NetMult*);
virtual void lpm_mux(const NetMux*);
virtual void lpm_ram_dq(const NetRamDq*);