📄 dump_memory_tf.c
字号:
/**********************************************************************
* $dump_mem example -- C source code using TF/ACC PLI routines
*
* C source to illustrate reading 4-state logic values from all
* addresses of a Verilog memory array.
*
* The logic values are represented as characters in the C language.
* Every eight bits of a Verilog memory word are passed to/from
* Verilog as a C structure containing a pair of C bytes (of type char),
* using an aval/bval encoding, where:
* 0/0 = logic 0, 1/0 = logic 1, 0/1 = logic Z, 1/1 = logic X.
*
* For the book, "The Verilog PLI Handbook" by Stuart Sutherland
* Book copyright 1999, Kluwer Academic Publishers, Norwell, MA, USA
* Contact: www.wkap.il
* Example copyright 1998, Sutherland HDL Inc, Portland, Oregon, USA
* Contact: www.sutherland.com or (503) 692-0898
*
* Usage:
* ------
* Syntax: $dump_mem_hex(<memory_word_select>);
* $dump_mem_ascii(<memory_word_select>);
*
* Note: The word select of the memory is ignored, but is
* required by the tf_nodeinfo() syntax.
*
* Example:
* reg [23:0] RAM [0:3];
* initial $ump_mem_hex(RAM[0]);
*
* Routine definitions for a veriusertfs array:
* /* routine prototypes -/
* extern int PLIbook_DumpMem_checktf(),
* PLIbook_DumpMem_calltf();
* /* table entries -/
* {usertask, /* type of PLI routine -/
* 0, /* user_data value -/
* PLIbook_DumpMem_checktf, /* checktf routine -/
* 0, /* sizetf routine -/
* PLIbook_DumpMem_calltf, /* calltf routine -/
* PLIbook_DumpMem_misctf, /* misctf routine -/
* "$dump_mem_hex", /* system task/function name -/
* 1 /* forward reference = true -/
* },
* {usertask, /* type of PLI routine -/
* 1, /* user_data value -/
* PLIbook_DumpMem_checktf, /* checktf routine -/
* 0, /* sizetf routine -/
* PLIbook_DumpMem_calltf, /* calltf routine -/
* PLIbook_DumpMem_misctf, /* misctf routine -/
* "$dump_mem_bin", /* system task/function name -/
* 1 /* forward reference = true -/
* },
* {usertask, /* type of PLI routine -/
* 2, /* user_data value -/
* PLIbook_DumpMem_checktf, /* checktf routine -/
* 0, /* sizetf routine -/
* PLIbook_DumpMem_calltf, /* calltf routine -/
* PLIbook_DumpMem_misctf, /* misctf routine -/
* "$dump_mem_ascii", /* system task/function name -/
* 1 /* forward reference = true -/
* },
**********************************************************************/
#include "veriuser.h" /* IEEE 1364 PLI TF routine library */
#define HEX 0 /* values of user_data for system task names */
#define BIN 1
#define ASCII 2
/**********************************************************************
* checktf routine
**********************************************************************/
int PLIbook_DumpMem_checktf(int user_data)
{
if (tf_nump() != 1)
if (user_data == HEX)
tf_error("Usage error: $dump_mem_hex(<memory_word_select>);");
else if (user_data == BIN)
tf_error("Usage error: $dump_mem_bin(<memory_word_select>);");
else
tf_error("Usage error: $dump_mem_ascii(<memory_word_select>);");
return(0);
}
/**********************************************************************
* misctf routine
*
* The misctf routine is used to call tf_nodeinfo() at the
* beginning of simulation, so that the memory allocated by
* tf_nodeinfo() is only allocated one time for each instance of
* $dump_mem_??.
**********************************************************************/
int PLIbook_DumpMem_misctf(int user_data, int reason)
{
p_tfnodeinfo node_info; /* pointer to structure for tf_nodeinfo() */
if (reason != REASON_ENDOFCOMPILE)
return(0); /* exit now if this is not the start of simulation */
/* allocate memory for an s_tfexprinfo structure */
node_info = (p_tfnodeinfo)malloc(sizeof(s_tfnodeinfo));
/* Get the nodeinfo structure for tfarg 1 */
if (!tf_nodeinfo(1, node_info)) {
tf_error("Err: $dump_mem_?? could not get tf_nodeinfo for tfarg 1");
tf_dofinish(); /* about simulation */
return(0);
}
else if (node_info->node_type != TF_MEMORY_NODE) {
tf_error("Err: $dump_mem_?? arg is not a memory word -- aborting");
tf_dofinish(); /* about simulation */
return(0);
}
else
tf_setworkarea((char *)node_info); /*put info pointer in workarea*/
return(0);
}
/**********************************************************************
* calltf routine
**********************************************************************/
/* prototypes of functions invoked by the calltf routine */
void PLIbook_DumpMemHex();
void PLIbook_DumpMemBin();
void PLIbook_DumpMemAscii();
int PLIbook_DumpMem_calltf(int user_data)
{
p_tfnodeinfo node_info;
node_info = (p_tfnodeinfo)tf_getworkarea();
io_printf("\nWithin PLI:\n");
io_printf(" Memory array width=%d depth=%d ngroups=%d\n",
node_info->node_vec_size,
node_info->node_mem_size,
node_info->node_ngroups);
io_printf("\n\nnode_ms_index = %d node_ls_index = %d\n\n",
node_info->node_ms_index, node_info->node_ls_index);
if (user_data == HEX) /* application called by $dump_mem_hex */
PLIbook_DumpMemHex(node_info);
else if (user_data == BIN) /* application called by $dump_mem_bin */
PLIbook_DumpMemBin(node_info);
else /* application called by $dump_mem_ascii */
PLIbook_DumpMemAscii(node_info);
return(0);
}
/**********************************************************************
* Function to dump each word of a Verilog array in hexadecimal
**********************************************************************/
void PLIbook_DumpMemHex(p_tfnodeinfo node_info)
{
char *aval_ptr, *bval_ptr;
int word_increment, mem_address, group_num;
io_printf(" Current memory contents of aval/bval groups in hex:\n");
word_increment = node_info->node_ngroups * 2;
for (mem_address = 0;
mem_address < node_info->node_mem_size;
mem_address++) {
io_printf(" address %d:\t ", mem_address);
/* set pointers to aval and bval words for the address */
aval_ptr = node_info->node_value.memoryval_p
+ (mem_address * word_increment);
bval_ptr = aval_ptr + node_info->node_ngroups;
/* print groups in word in reverse order so will match Verilog:
the highest group number represents the left-most byte of a
Verilog word, the lowest group represents the right-most byte */
for (group_num = node_info->node_ngroups - 1;
group_num >= 0;
group_num--) {
io_printf(" group %d: %x/%x",
group_num, aval_ptr[group_num], bval_ptr[group_num]);
}
io_printf("\n");
}
io_printf("\n\n");
return;
}
/**********************************************************************
* Function to dump each word of a Verilog array in ASCII
**********************************************************************/
void PLIbook_DumpMemAscii(p_tfnodeinfo node_info)
{
char *aval_ptr;
int word_increment, mem_address, group_num;
/* Read current memory values as a string using only aval bits */
io_printf(" Current memory contents in ASCII are:\n");
io_printf(" ");
word_increment = node_info->node_ngroups * 2;
for (mem_address = 0;
mem_address < node_info->node_mem_size;
mem_address++) {
/* set pointer to aval word for the address */
aval_ptr = node_info->node_value.memoryval_p
+ (mem_address * word_increment);
/* print groups in word in reverse order so will match Verilog:
the highest group number represents the left-most byte of a
Verilog word, the lowest group represents the right-most byte */
for (group_num = node_info->node_ngroups - 1;
group_num >= 0;
group_num--) {
io_printf("%c", aval_ptr[group_num]);
}
}
io_printf("\n\n");
return;
}
/* #define OBVIOUS /* compile more obvious, less efficient version */
#define EFFICIENT /* compile Drew's more efficient version */
#if defined EFFICIENT
/**********************************************************************
* Function to dump each word of a Verilog array in binary.
* This example of the function uses a more efficient C coding style to
* select one bit from a word.
**********************************************************************/
void PLIbook_DumpMemBin(p_tfnodeinfo node_info)
{
char *aval_ptr, *bval_ptr;
int word_increment, mem_address, word_bit;
char aval_val, bval_val;
io_printf(" Current memory contents in binary are:\n");
word_increment = node_info->node_ngroups * 2; /* 1 word = aval/bval pair */
for (mem_address = 0;
mem_address < node_info->node_mem_size;
mem_address++) {
/* set pointers to aval and bval words for the address */
aval_ptr = node_info->node_value.memoryval_p
+ (mem_address * word_increment);
bval_ptr = aval_ptr + node_info->node_ngroups;
io_printf(" address %d:\t ", mem_address);
/* print groups in word in reverse order so will match Verilog:
the highest group number represents the left-most byte of a
Verilog word, the lowest group represents the right-most byte */
for (word_bit = node_info->node_vec_size - 1;
word_bit >= 0;
word_bit--) {
aval_val = (aval_ptr[word_bit >> 3]) & (1 << (word_bit & 0x7));
bval_val = (bval_ptr[word_bit >> 3]) & (1 << (word_bit & 0x7));
/* translate aval/bval pair to 4-state logic value */
if (!bval_val) {
if (!aval_val) io_printf("0"); /* aval/bval == 0/0 */
else io_printf("1"); /* aval/bval == 1/0 */
}
else {
if (!aval_val) io_printf("z"); /* aval/bval == 0/1 */
else io_printf("x"); /* aval/bval == 1/1 */
}
}
io_printf("\n");
}
return;
}
#elif defined OBVIOUS
/**********************************************************************
* Function to dump each word of a Verilog array in binary.
* This example of the function uses a more obvious but less efficient
* C coding style to select one bit from a word.
**********************************************************************/
void PLIbook_DumpMemBin(p_tfnodeinfo node_info)
{
char *aval_ptr, *bval_ptr;
int word_increment, mem_address, word_bit, group_num, group_bit;
char aval_val, bval_val, bit_mask;
io_printf(" Current memory contents in binary are:\n");
word_increment = node_info->node_ngroups * 2;
for (mem_address = 0;
mem_address < node_info->node_mem_size;
mem_address++) {
io_printf(" address %d:\t ", mem_address);
/* step 1: set pointers to aval and bval words for the address */
aval_ptr = node_info->node_value.memoryval_p
+ (mem_address * word_increment);
bval_ptr = aval_ptr + node_info->node_ngroups;
for (word_bit = node_info->node_vec_size - 1;
word_bit >= 0;
word_bit--) {
/* step 2: determine the group which contains the bit number */
group_num = word_bit / 8;
/* step 3: determine which bit in the group contains the bit */
group_bit = word_bit % 8;
/* step 4: set an 8-bit mask to block all unwanted bits in group */
bit_mask = 0x01; /* Set mask to most-signif. bit of 8-bit group */
bit_mask = bit_mask << group_bit; /* Shift to bit to be modified */
/* step 5: select desired aval and bval bits from the groups */
aval_val = aval_ptr[group_num] & bit_mask;
bval_val = bval_ptr[group_num] & bit_mask;
/* translate aval/bval pair to 4-state logic value */
if (!bval_val) {
if (!aval_val) io_printf("0"); /* aval/bval == 0/0 */
else io_printf("1"); /* aval/bval == 1/0 */
}
else {
if (!aval_val) io_printf("z"); /* aval/bval == 0/1 */
else io_printf("x"); /* aval/bval == 1/1 */
}
}
io_printf("\n");
}
io_printf("\n");
return;
}
#endif
/*********************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -