Add code generator hooks for latches
Add code generator hooks missing from the previous patches that add latch synthesis support.
This commit is contained in:
parent
f600e774d5
commit
3d0a2aba2c
12
NetLatch.cc
12
NetLatch.cc
|
|
@ -3,6 +3,7 @@
|
||||||
// Class NetLatch member-function definitions
|
// Class NetLatch member-function definitions
|
||||||
|
|
||||||
#include "NetLatch.h" // NetLatch class definition
|
#include "NetLatch.h" // NetLatch class definition
|
||||||
|
#include "target.h" // target_t structure definition
|
||||||
|
|
||||||
// constructor
|
// constructor
|
||||||
NetLatch::NetLatch( NetScope *scope, perm_string name, unsigned width )
|
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
|
} // end NetLatch constructor
|
||||||
|
|
||||||
|
unsigned NetLatch::width() const
|
||||||
|
{
|
||||||
|
return ( pin_count() - 1U ) / 2U;
|
||||||
|
} // end function width
|
||||||
|
|
||||||
Link &NetLatch::pin_Data( unsigned w )
|
Link &NetLatch::pin_Data( unsigned w )
|
||||||
{
|
{
|
||||||
unsigned pn = 1 + 2 * w;
|
unsigned pn = 1 + 2 * w;
|
||||||
|
|
@ -29,3 +35,9 @@ Link &NetLatch::pin_Gate()
|
||||||
{
|
{
|
||||||
return pin( 0 );
|
return pin( 0 );
|
||||||
} // end function pin_Q
|
} // end function pin_Q
|
||||||
|
|
||||||
|
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:
|
public:
|
||||||
NetLatch( NetScope *, perm_string, unsigned );
|
NetLatch( NetScope *, perm_string, unsigned );
|
||||||
|
|
||||||
|
unsigned width() const;
|
||||||
|
|
||||||
Link &pin_Data( unsigned );
|
Link &pin_Data( unsigned );
|
||||||
Link &pin_Q( unsigned );
|
Link &pin_Q( unsigned );
|
||||||
Link &pin_Gate();
|
Link &pin_Gate();
|
||||||
|
|
@ -25,6 +27,8 @@ class NetLatch : public NetNode
|
||||||
const Link &pin_Data( unsigned ) const;
|
const Link &pin_Data( unsigned ) const;
|
||||||
const Link &pin_Q( unsigned ) const;
|
const Link &pin_Q( unsigned ) const;
|
||||||
const Link &pin_Gate() const;
|
const Link &pin_Gate() const;
|
||||||
|
|
||||||
|
virtual bool emit_node( target_t * ) const;
|
||||||
}; // end class NetLatch
|
}; // end class NetLatch
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -230,6 +230,7 @@ typedef enum ivl_lpm_type_e {
|
||||||
IVL_LPM_DEMUX = 16,
|
IVL_LPM_DEMUX = 16,
|
||||||
IVL_LPM_DIVIDE = 12,
|
IVL_LPM_DIVIDE = 12,
|
||||||
IVL_LPM_FF = 3,
|
IVL_LPM_FF = 3,
|
||||||
|
IVL_LPM_LATCH = 17,
|
||||||
IVL_LPM_MOD = 13,
|
IVL_LPM_MOD = 13,
|
||||||
IVL_LPM_MULT = 4,
|
IVL_LPM_MULT = 4,
|
||||||
IVL_LPM_MUX = 5,
|
IVL_LPM_MUX = 5,
|
||||||
|
|
|
||||||
|
|
@ -231,7 +231,6 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope, bool sync_flag,
|
||||||
}
|
}
|
||||||
|
|
||||||
des->add_node( latchPtr );
|
des->add_node( latchPtr );
|
||||||
delete latchPtr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
catch ( bad_alloc &memoryAllocationException )
|
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
|
* 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
|
* 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,
|
bool NetCondit::synth_async(Design*des, NetScope*scope, bool sync_flag,
|
||||||
struct sync_accounting_cell*nex_ff,
|
struct sync_accounting_cell*nex_ff,
|
||||||
|
|
|
||||||
|
|
@ -1084,6 +1084,8 @@ extern "C" unsigned ivl_lpm_width(ivl_lpm_t net)
|
||||||
case IVL_LPM_FF:
|
case IVL_LPM_FF:
|
||||||
case IVL_LPM_RAM:
|
case IVL_LPM_RAM:
|
||||||
return net->u_.ff.width;
|
return net->u_.ff.width;
|
||||||
|
case IVL_LPM_LATCH:
|
||||||
|
return net->u_.latch.width;
|
||||||
case IVL_LPM_DECODE:
|
case IVL_LPM_DECODE:
|
||||||
case IVL_LPM_MUX:
|
case IVL_LPM_MUX:
|
||||||
return net->u_.mux.width;
|
return net->u_.mux.width;
|
||||||
|
|
|
||||||
27
t-dll.cc
27
t-dll.cc
|
|
@ -33,6 +33,9 @@
|
||||||
#endif
|
#endif
|
||||||
# include <stdlib.h>
|
# include <stdlib.h>
|
||||||
|
|
||||||
|
#include <new> // standard operator new
|
||||||
|
using std::bad_alloc;
|
||||||
|
|
||||||
#if defined(__WIN32__)
|
#if defined(__WIN32__)
|
||||||
|
|
||||||
inline ivl_dll_t ivl_dlopen(const char *name)
|
inline ivl_dll_t ivl_dlopen(const char *name)
|
||||||
|
|
@ -1734,6 +1737,30 @@ 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 );
|
||||||
|
}
|
||||||
|
catch ( bad_alloc &memoryAllocationException )
|
||||||
|
{
|
||||||
|
cerr << "Exception occurred: " << memoryAllocationException.what() << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end function lpm_latch
|
||||||
|
|
||||||
void dll_target::lpm_ram_dq(const NetRamDq*net)
|
void dll_target::lpm_ram_dq(const NetRamDq*net)
|
||||||
{
|
{
|
||||||
ivl_memory_t mem = find_memory(des_, net->mem());
|
ivl_memory_t mem = find_memory(des_, net->mem());
|
||||||
|
|
|
||||||
5
t-dll.h
5
t-dll.h
|
|
@ -80,6 +80,7 @@ struct dll_target : public target_t, public expr_scan_t {
|
||||||
bool lpm_demux(const NetDemux*);
|
bool lpm_demux(const NetDemux*);
|
||||||
void lpm_divide(const NetDivide*);
|
void lpm_divide(const NetDivide*);
|
||||||
void lpm_ff(const NetFF*);
|
void lpm_ff(const NetFF*);
|
||||||
|
void lpm_latch( const NetLatch * );
|
||||||
void lpm_modulo(const NetModulo*);
|
void lpm_modulo(const NetModulo*);
|
||||||
void lpm_mult(const NetMult*);
|
void lpm_mult(const NetMult*);
|
||||||
void lpm_mux(const NetMux*);
|
void lpm_mux(const NetMux*);
|
||||||
|
|
@ -328,6 +329,10 @@ struct ivl_lpm_s {
|
||||||
ivl_expr_t sset_value;
|
ivl_expr_t sset_value;
|
||||||
} ff;
|
} ff;
|
||||||
|
|
||||||
|
struct ivl_lpm_latch_s {
|
||||||
|
unsigned width;
|
||||||
|
} latch;
|
||||||
|
|
||||||
struct ivl_lpm_mux_s {
|
struct ivl_lpm_mux_s {
|
||||||
unsigned width;
|
unsigned width;
|
||||||
unsigned size;
|
unsigned size;
|
||||||
|
|
|
||||||
|
|
@ -133,6 +133,11 @@ void target_t::lpm_ff(const NetFF*)
|
||||||
"Unhandled NetFF." << endl;
|
"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*)
|
void target_t::lpm_mult(const NetMult*)
|
||||||
{
|
{
|
||||||
cerr << "target (" << typeid(*this).name() << "): "
|
cerr << "target (" << typeid(*this).name() << "): "
|
||||||
|
|
|
||||||
2
target.h
2
target.h
|
|
@ -23,6 +23,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
# include "netlist.h"
|
# include "netlist.h"
|
||||||
|
#include "NetLatch.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This header file describes the types and constants used to describe
|
* 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_divide(const NetDivide*);
|
||||||
virtual void lpm_modulo(const NetModulo*);
|
virtual void lpm_modulo(const NetModulo*);
|
||||||
virtual void lpm_ff(const NetFF*);
|
virtual void lpm_ff(const NetFF*);
|
||||||
|
virtual void lpm_latch( const NetLatch * );
|
||||||
virtual void lpm_mult(const NetMult*);
|
virtual void lpm_mult(const NetMult*);
|
||||||
virtual void lpm_mux(const NetMux*);
|
virtual void lpm_mux(const NetMux*);
|
||||||
virtual void lpm_ram_dq(const NetRamDq*);
|
virtual void lpm_ram_dq(const NetRamDq*);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue