Generate code to support memory access in continuous

assignment statements. (Stephan Boettcher)
This commit is contained in:
steve 2001-06-16 02:41:41 +00:00
parent b75221e9bf
commit bf42772995
5 changed files with 254 additions and 17 deletions

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: ivl_target.h,v 1.66 2001/06/15 04:14:18 steve Exp $"
#ident "$Id: ivl_target.h,v 1.67 2001/06/16 02:41:41 steve Exp $"
#endif
#ifdef __cplusplus
@ -206,7 +206,8 @@ typedef enum ivl_lpm_type_e {
IVL_LPM_CMP_GT,
IVL_LPM_FF,
IVL_LPM_MUX,
IVL_LPM_SUB
IVL_LPM_SUB,
IVL_LPM_RAM,
} ivl_lpm_type_t;
/* Processes are initial or always blocks with a statement. This is
@ -500,7 +501,8 @@ extern const char* ivl_udp_name(ivl_udp_t net);
* output vector. This is most devices, it turns out.
*
* ivl_lpm_selects
* This is the size of the select input for a LPM_MUX device
* This is the size of the select input for a LPM_MUX device, or the
* address bus width of an LPM_RAM.
*
* ivl_lpm_size
* In addition to a width, some devices have a size. The size is
@ -511,22 +513,26 @@ extern const char* ivl_lpm_name(ivl_lpm_t net);
extern ivl_lpm_type_t ivl_lpm_type(ivl_lpm_t net);
extern unsigned ivl_lpm_width(ivl_lpm_t net);
/* IVL_LPM_FF */
/* IVL_LPM_FF IVL_LPM_RAM */
extern ivl_nexus_t ivl_lpm_clk(ivl_lpm_t net);
/* IVL_LPM_ADD IVL_LPM_FF IVL_LPM_SUB */
/* IVL_LPM_RAM */
extern ivl_nexus_t ivl_lpm_enable(ivl_lpm_t net);
/* IVL_LPM_ADD IVL_LPM_FF IVL_LPM_RAM IVL_LPM_SUB */
extern ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx);
/* IVL_LPM_ADD IVL_LPM_SUB */
extern ivl_nexus_t ivl_lpm_datab(ivl_lpm_t net, unsigned idx);
/* IVL_LPM_MUX */
extern ivl_nexus_t ivl_lpm_data2(ivl_lpm_t net, unsigned sdx, unsigned idx);
/* IVL_LPM_ADD IVL_LPM_FF IVL_LPM_SUB */
/* IVL_LPM_ADD IVL_LPM_FF IVL_LPM_RAM IVL_LPM_SUB */
extern ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx);
/* IVL_LPM_MUX */
/* IVL_LPM_MUX IVL_LPM_RAM */
extern unsigned ivl_lpm_selects(ivl_lpm_t net);
/* IVL_LPM_MUX */
/* IVL_LPM_MUX IVL_LPM_RAM */
extern ivl_nexus_t ivl_lpm_select(ivl_lpm_t net, unsigned idx);
/* IVL_LPM_MUX */
extern unsigned ivl_lpm_size(ivl_lpm_t net);
/* IVL_LPM_RAM */
extern ivl_memory_t ivl_lpm_memory(ivl_lpm_t net);
/* LVAL
@ -875,6 +881,10 @@ _END_DECL
/*
* $Log: ivl_target.h,v $
* Revision 1.67 2001/06/16 02:41:41 steve
* Generate code to support memory access in continuous
* assignment statements. (Stephan Boettcher)
*
* Revision 1.66 2001/06/15 04:14:18 steve
* Generate vvp code for GT and GE comparisons.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: t-dll-api.cc,v 1.49 2001/06/15 04:14:19 steve Exp $"
#ident "$Id: t-dll-api.cc,v 1.50 2001/06/16 02:41:41 steve Exp $"
#endif
# include "t-dll.h"
@ -438,6 +438,7 @@ extern "C" ivl_nexus_t ivl_lpm_clk(ivl_lpm_t net)
assert(net);
switch (net->type) {
case IVL_LPM_FF:
case IVL_LPM_RAM:
return net->u_.ff.clk;
default:
assert(0);
@ -445,6 +446,18 @@ extern "C" ivl_nexus_t ivl_lpm_clk(ivl_lpm_t net)
}
}
extern "C" ivl_nexus_t ivl_lpm_enable(ivl_lpm_t net)
{
assert(net);
switch (net->type) {
case IVL_LPM_RAM:
return net->u_.ff.we;
default:
assert(0);
return 0;
}
}
extern "C" ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx)
{
assert(net);
@ -457,6 +470,7 @@ extern "C" ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx)
return net->u_.arith.a[idx];
case IVL_LPM_FF:
case IVL_LPM_RAM:
assert(idx < net->u_.ff.width);
if (net->u_.ff.width == 1)
return net->u_.ff.d.pin;
@ -523,6 +537,7 @@ extern "C" ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx)
return net->u_.arith.q[0];
case IVL_LPM_FF:
case IVL_LPM_RAM:
assert(idx < net->u_.ff.width);
if (net->u_.ff.width == 1)
return net->u_.ff.q.pin;
@ -545,6 +560,13 @@ extern "C" ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx)
extern "C" ivl_nexus_t ivl_lpm_select(ivl_lpm_t net, unsigned idx)
{
switch (net->type) {
case IVL_LPM_RAM:
assert(idx < net->u_.ff.swid);
if (net->u_.ff.swid == 1)
return net->u_.ff.s.pin;
else
return net->u_.ff.s.pins[idx];
case IVL_LPM_MUX:
assert(idx < net->u_.mux.swid);
if (net->u_.mux.swid == 1)
@ -561,6 +583,8 @@ extern "C" ivl_nexus_t ivl_lpm_select(ivl_lpm_t net, unsigned idx)
extern "C" unsigned ivl_lpm_selects(ivl_lpm_t net)
{
switch (net->type) {
case IVL_LPM_RAM:
return net->u_.ff.swid;
case IVL_LPM_MUX:
return net->u_.mux.swid;
default:
@ -590,6 +614,7 @@ extern "C" unsigned ivl_lpm_width(ivl_lpm_t net)
assert(net);
switch (net->type) {
case IVL_LPM_FF:
case IVL_LPM_RAM:
return net->u_.ff.width;
case IVL_LPM_MUX:
return net->u_.mux.width;
@ -604,6 +629,18 @@ extern "C" unsigned ivl_lpm_width(ivl_lpm_t net)
}
}
extern "C" ivl_memory_t ivl_lpm_memory(ivl_lpm_t net)
{
assert(net);
switch (net->type) {
case IVL_LPM_RAM:
return net->u_.ff.mem;
default:
assert(0);
return 0;
}
}
extern "C" ivl_expr_t ivl_lval_mux(ivl_lval_t net)
{
assert(net);
@ -1186,6 +1223,10 @@ extern "C" ivl_statement_t ivl_stmt_sub_stmt(ivl_statement_t net)
/*
* $Log: t-dll-api.cc,v $
* Revision 1.50 2001/06/16 02:41:41 steve
* Generate code to support memory access in continuous
* assignment statements. (Stephan Boettcher)
*
* Revision 1.49 2001/06/15 04:14:19 steve
* Generate vvp code for GT and GE comparisons.
*

119
t-dll.cc
View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: t-dll.cc,v 1.47 2001/06/15 05:01:09 steve Exp $"
#ident "$Id: t-dll.cc,v 1.48 2001/06/16 02:41:42 steve Exp $"
#endif
# include "compiler.h"
@ -820,6 +820,119 @@ void dll_target::lpm_ff(const NetFF*net)
}
}
void dll_target::lpm_ram_dq(const NetRamDq*net)
{
ivl_lpm_t obj = new struct ivl_lpm_s;
obj->type = IVL_LPM_RAM;
obj->name = strdup(net->name());
obj->u_.ff.mem = lookup_memory_(net->mem());
assert(obj->u_.ff.mem);
obj->scope = find_scope(des_.root_, net->mem()->scope());
assert(obj->scope);
obj->u_.ff.width = net->width();
obj->u_.ff.swid = net->awidth();
scope_add_lpm(obj->scope, obj);
const Nexus*nex;
// How do I find out if there is something
// connected to the clock input?
bool has_write_port = false;
// Connect the write clock and write enable
if (has_write_port) {
nex = net->pin_InClock().nexus();
assert(nex->t_cookie());
obj->u_.ff.clk = (ivl_nexus_t) nex->t_cookie();
assert(obj->u_.ff.clk);
nexus_lpm_add(obj->u_.ff.clk, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
nex = net->pin_WE().nexus();
if (nex && nex->t_cookie()) {
obj->u_.ff.we = (ivl_nexus_t) nex->t_cookie();
assert(obj->u_.ff.we);
nexus_lpm_add(obj->u_.ff.we, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
}
else
obj->u_.ff.we = 0x0;
}
else {
obj->u_.ff.clk = 0x0;
obj->u_.ff.we = 0x0;
}
// Connect the address bus
if (obj->u_.ff.swid == 1) {
nex = net->pin_Address(0).nexus();
assert(nex->t_cookie());
obj->u_.ff.s.pin = (ivl_nexus_t) nex->t_cookie();
nexus_lpm_add(obj->u_.ff.s.pin, obj, 0,
IVL_DR_STRONG, IVL_DR_STRONG);
}
else {
obj->u_.ff.s.pins = new ivl_nexus_t [obj->u_.ff.swid];
for (unsigned idx = 0 ; idx < obj->u_.ff.swid ; idx += 1) {
nex = net->pin_Address(idx).nexus();
assert(nex->t_cookie());
obj->u_.ff.s.pins[idx] = (ivl_nexus_t) nex->t_cookie();
nexus_lpm_add(obj->u_.ff.s.pins[idx], obj, 0,
IVL_DR_STRONG, IVL_DR_STRONG);
}
}
// Connect the data busses
if (obj->u_.ff.width == 1) {
nex = net->pin_Q(0).nexus();
assert(nex->t_cookie());
obj->u_.ff.q.pin = (ivl_nexus_t) nex->t_cookie();
nexus_lpm_add(obj->u_.ff.q.pin, obj, 0,
IVL_DR_STRONG, IVL_DR_STRONG);
if (has_write_port) {
nex = net->pin_Data(0).nexus();
assert(nex->t_cookie());
obj->u_.ff.d.pin = (ivl_nexus_t) nex->t_cookie();
nexus_lpm_add(obj->u_.ff.d.pin, obj,
0, IVL_DR_HiZ, IVL_DR_HiZ);
}
}
else if (has_write_port) {
obj->u_.ff.q.pins = new ivl_nexus_t [obj->u_.ff.width * 2];
obj->u_.ff.d.pins = obj->u_.ff.q.pins + obj->u_.ff.width;
for (unsigned idx = 0 ; idx < obj->u_.ff.width ; idx += 1) {
nex = net->pin_Q(idx).nexus();
assert(nex->t_cookie());
obj->u_.ff.q.pins[idx] = (ivl_nexus_t) nex->t_cookie();
nexus_lpm_add(obj->u_.ff.q.pins[idx], obj, 0,
IVL_DR_STRONG, IVL_DR_STRONG);
nex = net->pin_Data(idx).nexus();
assert(nex->t_cookie());
obj->u_.ff.d.pins[idx] = (ivl_nexus_t) nex->t_cookie();
nexus_lpm_add(obj->u_.ff.d.pins[idx], obj, 0,
IVL_DR_HiZ, IVL_DR_HiZ);
}
}
else {
obj->u_.ff.q.pins = new ivl_nexus_t [obj->u_.ff.width];
for (unsigned idx = 0 ; idx < obj->u_.ff.width ; idx += 1) {
nex = net->pin_Q(idx).nexus();
assert(nex->t_cookie());
obj->u_.ff.q.pins[idx] = (ivl_nexus_t) nex->t_cookie();
nexus_lpm_add(obj->u_.ff.q.pins[idx], obj, 0,
IVL_DR_STRONG, IVL_DR_STRONG);
}
}
}
void dll_target::lpm_mux(const NetMux*net)
{
ivl_lpm_t obj = new struct ivl_lpm_s;
@ -1180,6 +1293,10 @@ extern const struct target tgt_dll = { "dll", &dll_target_obj };
/*
* $Log: t-dll.cc,v $
* Revision 1.48 2001/06/16 02:41:42 steve
* Generate code to support memory access in continuous
* assignment statements. (Stephan Boettcher)
*
* Revision 1.47 2001/06/15 05:01:09 steve
* support LE and LT comparators.
*

14
t-dll.h
View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: t-dll.h,v 1.47 2001/06/15 04:14:19 steve Exp $"
#ident "$Id: t-dll.h,v 1.48 2001/06/16 02:41:42 steve Exp $"
#endif
# include "target.h"
@ -65,6 +65,7 @@ struct dll_target : public target_t, public expr_scan_t {
void lpm_compare(const NetCompare*);
void lpm_ff(const NetFF*);
void lpm_mux(const NetMux*);
void lpm_ram_dq(const NetRamDq*);
void net_assign(const NetAssign_*);
bool net_const(const NetConst*);
void net_probe(const NetEvProbe*);
@ -223,7 +224,9 @@ struct ivl_lpm_s {
union {
struct ivl_lpm_ff_s {
unsigned short width;
unsigned short swid; // ram only
ivl_nexus_t clk;
ivl_nexus_t we; // ram only ??
union {
ivl_nexus_t*pins;
ivl_nexus_t pin;
@ -232,6 +235,11 @@ struct ivl_lpm_s {
ivl_nexus_t*pins;
ivl_nexus_t pin;
} d;
union { // ram only
ivl_nexus_t*pins;
ivl_nexus_t pin;
} s;
ivl_memory_t mem; // ram only
} ff;
struct ivl_lpm_mux_s {
@ -529,6 +537,10 @@ struct ivl_statement_s {
/*
* $Log: t-dll.h,v $
* Revision 1.48 2001/06/16 02:41:42 steve
* Generate code to support memory access in continuous
* assignment statements. (Stephan Boettcher)
*
* Revision 1.47 2001/06/15 04:14:19 steve
* Generate vvp code for GT and GE comparisons.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: vvp_scope.c,v 1.32 2001/06/15 04:14:19 steve Exp $"
#ident "$Id: vvp_scope.c,v 1.33 2001/06/16 02:41:42 steve Exp $"
#endif
# include "vvp_priv.h"
@ -115,6 +115,7 @@ static const char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr)
}
break;
case IVL_LPM_RAM:
case IVL_LPM_ADD:
case IVL_LPM_SUB:
for (idx = 0 ; idx < ivl_lpm_width(lpm) ; idx += 1)
@ -619,6 +620,53 @@ static void draw_event_in_scope(ivl_event_t obj)
}
}
inline static void draw_lpm_ram(ivl_lpm_t net)
{
unsigned idx;
unsigned width = ivl_lpm_width(net);
unsigned awidth = ivl_lpm_selects(net);
ivl_memory_t mem = ivl_lpm_memory(net);
ivl_nexus_t clk = ivl_lpm_clk(net);
ivl_nexus_t pin;
if (clk) {
fprintf(vvp_out,
"CLK_%s .event posedge, ",
ivl_lpm_name(net));
draw_input_from_net(pin);
fprintf(vvp_out, ";\n");
}
fprintf(vvp_out,
"L_%s .mem/port M_%s, %d,0, %d,\n ",
ivl_lpm_name(net),
ivl_memory_name(mem),
width-1,
awidth);
for (idx = 0 ; idx < awidth ; idx += 1) {
pin = ivl_lpm_select(net, idx);
if (idx) fprintf(vvp_out, ", ");
draw_input_from_net(pin);
}
if (clk) {
fprintf(vvp_out, ",\n CLK_%s, ", ivl_lpm_name(net));
pin = ivl_lpm_enable(net);
if (pin)
draw_input_from_net(pin);
else
fprintf(vvp_out, "C<1>");
for (idx=0; idx<width; idx++) {
pin = ivl_lpm_data(net, idx);
fprintf(vvp_out, ", ");
draw_input_from_net(pin);
}
}
fprintf(vvp_out, ";\n");
}
static void draw_lpm_arith_a_b_inputs(ivl_lpm_t net)
{
unsigned width = ivl_lpm_width(net);
@ -724,6 +772,11 @@ static void draw_lpm_mux(ivl_lpm_t net)
static void draw_lpm_in_scope(ivl_lpm_t net)
{
switch (ivl_lpm_type(net)) {
case IVL_LPM_RAM:
draw_lpm_ram(net);
return;
case IVL_LPM_ADD:
case IVL_LPM_SUB:
draw_lpm_add(net);
@ -801,16 +854,16 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent)
draw_event_in_scope(event);
}
for (idx = 0 ; idx < ivl_scope_lpms(net) ; idx += 1) {
ivl_lpm_t lpm = ivl_scope_lpm(net, idx);
draw_lpm_in_scope(lpm);
}
for (idx = 0 ; idx < ivl_scope_mems(net) ; idx += 1) {
ivl_memory_t mem = ivl_scope_mem(net, idx);
draw_mem_in_scope(mem);
}
for (idx = 0 ; idx < ivl_scope_lpms(net) ; idx += 1) {
ivl_lpm_t lpm = ivl_scope_lpm(net, idx);
draw_lpm_in_scope(lpm);
}
if (ivl_scope_type(net) == IVL_SCT_TASK)
draw_task_definition(net);
@ -823,6 +876,10 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent)
/*
* $Log: vvp_scope.c,v $
* Revision 1.33 2001/06/16 02:41:42 steve
* Generate code to support memory access in continuous
* assignment statements. (Stephan Boettcher)
*
* Revision 1.32 2001/06/15 04:14:19 steve
* Generate vvp code for GT and GE comparisons.
*