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:
parent
f600e774d5
commit
5cae6b64af
19
NetLatch.cc
19
NetLatch.cc
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
49
t-dll-api.cc
49
t-dll-api.cc
|
|
@ -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;
|
||||
|
|
|
|||
30
t-dll.cc
30
t-dll.cc
|
|
@ -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());
|
||||
|
|
|
|||
9
t-dll.h
9
t-dll.h
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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() << "): "
|
||||
|
|
|
|||
2
target.h
2
target.h
|
|
@ -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*);
|
||||
|
|
|
|||
Loading…
Reference in New Issue