SoC的Testbench中的简易bus_monitor(加入print函数)

主要思路 向固定地址写信息

  • 使用工具链将C写的print/printf函数编译成hex文件
  • 在testbench中创建bus_monitor来监控总线上信息
    • 当监控print对总线上的固定地址操作时将数据存储到预先定义的memory中
    • 使用verilog的write处理memory中的ASCII码,打印到屏幕上

testbench下的bus_monitor

module bus_monitor();

`define DIGITAL_TOP testbench.u0_riscv_platform_demo.u0_digital_top
`define BUSMON `DIGITAL_TOP.u0_Insight_E21_ECoreIPSubsystem `define LED_DRIVER_BASE (32'h4FF00000) //4FF0_0000
`define LED_RETURN_CHAR 16'h0a
`define LED_FINISH 16'h00
//RISCV
`define RISCV_START 16'h80 // "Test start by RISCV";
`define RISCV_FINISH 16'h81 // "Test complete by RISCV";
`define RISCV_FAIL 16'h82 // "Msg code FAIL by RISCV";
`define RISCV_PASS 16'h83 // "Msg code PASS by RISCV"; //open Memory For CPU Print Messeage storge
parameter ADDR_DEPTH =15;
parameter WORD_DEPTH = (1<<ADDR_DEPTH) ; // Memory depth in K,16bit
reg [7:0] memory [0:(WORD_DEPTH - 1)]; // Memory register array
reg [7:0] led_data; reg led_valid;
wire cclk = `DIGITAL_TOP.cpu_clock; wire [7:0] ext_mem_din = `BUSMON.sys_port_ahb_0_hwdata[7:0];
always @(posedge cclk) begin
led_valid <= (`BUSMON.sys_port_ahb_0_haddr == `LED_DRIVER_BASE)
&& `BUSMON.sys_port_ahb_0_hwrite
&& `BUSMON.sys_port_ahb_0_hsel;
end // wire [7:0] ext_mem_din = `BUSMON.E31.auto_rational_xing_sourcelzy_out_a_bits1_data[31:0];
// always @(posedge cclk) begin
// led_valid <= (`BUSMON.E31.auto_rational_xing_sourcelzy_out_a_bits0_address[31:0] == `LED_DRIVER_BASE)
// && `BUSMON.E31.auto_rational_xing_sourcelzy_out_a_valid;
// end integer i;
integer m;
initial begin
i=0;
m=0;
end always @ (negedge cclk)
begin
if (led_valid)
begin
led_data = ext_mem_din[7:0];
if(ext_mem_din[7]== 1'b1)
print_code(ext_mem_din[7:0]);
else
case(ext_mem_din[7:0])
`LED_RETURN_CHAR: begin // Nul character check by monitor
memory[i] = ext_mem_din[7:0];
i=i+1;
for(m=0;m<i;m=m+1) begin
$write ("%c",memory[m]);
end
i=0;
end
`LED_FINISH: begin //$finish test
$display ("Terminate detect by bus_monitor - mcu terminating simulation\n");
#100 $finish;
end
default: begin
memory[i] = ext_mem_din[7:0];
i=i+1;
end
endcase
end
end task print_code;
input [7:0] code; reg [8*60:1] message;
begin
case (code)
// RISCV Signal
`RISCV_START : message = "Test start by RISCV";
`RISCV_FINISH : message = "Test complete by RISCV";
`RISCV_FAIL : message = "Msg code FAIL by RISCV";
`RISCV_PASS : message = "Msg code PASS by RISCV";
default : message = "Unrecognized message code";
endcase
$display ("print_code message: %0s (Msg code %h)", message, code);
end
endtask endmodule

print/printf函数(C代码)

注意:向一个固定的总线地址写信息

sim_show.h

#define LED_REG_BASE         0x4FF00000

// Global Signal
#define RISCV_QUIT 0x00 // "NULL Char detected by led_model";
// RISCV Signal
#define RISCV_START 0x80 // "Test start by RISCV";
#define RISCV_FINISH 0x81 // "Test complete by RISCV";
#define RISCV_FAIL 0x82 // "Msg code FAIL by RISCV";
#define RISCV_PASS 0x83 // "Msg code PASS by RISCV"; void sim_start();
void sim_pass();
void sim_fail();
void sim_finish();
void print_led(char string_val []);
void printf_led(const char* fmt, ...);

sim_show.c

可移植的print底层函数

#include <stdint.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h> #include <stddef.h> // headers for the print functions
#include <stdarg.h> // support variable length arguments (printf)
#include <string.h>
#include "sim_show.h" void sim_start() {
*(volatile char *)LED_REG_BASE = RISCV_START;
} void sim_pass() {
*(volatile char *)LED_REG_BASE = RISCV_PASS;
*(volatile char *)LED_REG_BASE = RISCV_QUIT;
} void sim_fail() {
*(volatile char *)LED_REG_BASE = RISCV_FAIL;
*(volatile char *)LED_REG_BASE = RISCV_QUIT;
} void sim_finish() {
*(volatile char *)LED_REG_BASE = RISCV_FINISH;
*(volatile char *)LED_REG_BASE = RISCV_QUIT;
} // print_led - print any size constant array of characters to the LED driver
// - faster than printf_led but less robust
void print_led(char string_val []) {
int i;
for(i=0;string_val[i] != '\0';i++) {
*(volatile char *)LED_REG_BASE = string_val[i];
}
} // void print_led() static void sprintf_putch(int ch, void** data)
{
char** pstr = (char**)data;
**pstr = ch;
(*pstr)++;
} int putchar(int ch)
{
*(volatile char *)LED_REG_BASE = ch; } static unsigned long getuint(va_list *ap, int lflag)
{
if (lflag)
return va_arg(*ap, unsigned long);
else
return va_arg(*ap, unsigned int);
} static long getint(va_list *ap, int lflag)
{
if (lflag)
return va_arg(*ap, long);
else
return va_arg(*ap, int);
} static inline void printnum(void (*putch)(int, void**), void **putdat,
uint64_t num, unsigned base, int width, int padc)
{
unsigned digs[sizeof(num)*8];
int pos = 0; while (1)
{
digs[pos++] = num % base;
if (num < base)
break;
num /= base;
} while (width-- > pos)
putch(padc, putdat); while (pos-- > 0)
putch(digs[pos] + (digs[pos] >= 10 ? 'a' - 10 : '0'), putdat);
} static inline void print_double(void (*putch)(int, void**), void **putdat,
double num, int width, int prec)
{
union {
double d;
uint64_t u;
} u;
u.d = num; if (u.u & (1ULL << 63)) {
putch('-', putdat);
u.u &= ~(1ULL << 63);
} for (int i = 0; i < prec; i++)
u.d *= 10; char buf[32], *pbuf = buf;
printnum(sprintf_putch, (void**)&pbuf, (uint64_t)u.d, 10, 0, 0);
if (prec > 0) {
for (int i = 0; i < prec; i++) {
pbuf[-i] = pbuf[-i-1];
}
pbuf[-prec] = '.';
pbuf++;
} for (char* p = buf; p < pbuf; p++)
putch(*p, putdat);
} static void vprintfmt(void (*putch)(int, void**), void **putdat, const char *fmt, va_list ap)
{
register const char* p;
const char* last_fmt;
register int ch, err;
unsigned long num;
int base, lflag, width, precision, altflag;
char padc; while (1) {
while ((ch = *(unsigned char *) fmt) != '%') {
if (ch == '\0')
return;
fmt++;
putch(ch, putdat);
}
fmt++; // Process a %-escape sequence
last_fmt = fmt;
padc = ' ';
width = -1;
precision = -1;
lflag = 0;
altflag = 0;
reswitch:
switch (ch = *(unsigned char *) fmt++) { // flag to pad on the right
case '-':
padc = '-';
goto reswitch; // flag to pad with 0's instead of spaces
case '0':
padc = '0';
goto reswitch; // width field
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
for (precision = 0; ; ++fmt) {
precision = precision * 10 + ch - '0';
ch = *fmt;
if (ch < '0' || ch > '9')
break;
}
goto process_precision; case '*':
precision = va_arg(ap, int);
goto process_precision; case '.':
if (width < 0)
width = 0;
goto reswitch; case '#':
altflag = 1;
goto reswitch; process_precision:
if (width < 0)
width = precision, precision = -1;
goto reswitch; // long flag
case 'l':
if (lflag)
goto bad;
goto reswitch; // character
case 'c':
putch(va_arg(ap, int), putdat);
break; // double
case 'f':
print_double(putch, putdat, va_arg(ap, double), width, precision);
break; // string
case 's':
if ((p = va_arg(ap, char *)) == NULL)
p = "(null)";
if (width > 0 && padc != '-')
for (width -= strnlen(p, precision); width > 0; width--)
putch(padc, putdat);
for (; (ch = *p) != '\0' && (precision < 0 || --precision >= 0); width--) {
putch(ch, putdat);
p++;
}
for (; width > 0; width--)
putch(' ', putdat);
break; // (signed) decimal
case 'd':
num = getint(&ap, lflag);
if ((long) num < 0) {
putch('-', putdat);
num = -(long) num;
}
base = 10;
goto signed_number; // unsigned decimal
case 'u':
base = 10;
goto unsigned_number; // (unsigned) octal
case 'o':
// should do something with padding so it's always 3 octits
base = 8;
goto unsigned_number; // pointer
case 'p':
lflag = 1;
putch('0', putdat);
putch('x', putdat);
/* fall through to 'x' */ // (unsigned) hexadecimal
case 'x':
base = 16;
unsigned_number:
num = getuint(&ap, lflag);
signed_number:
printnum(putch, putdat, num, base, width, padc);
break; // escaped '%' character
case '%':
putch(ch, putdat);
break; // unrecognized escape sequence - just print it literally
default:
bad:
putch('%', putdat);
fmt = last_fmt;
break;
}
}
} void printf_led(const char* fmt, ...)
{
va_list ap;
va_start(ap, fmt); vprintfmt((void *)putchar, 0, fmt, ap); va_end(ap);
}

仿真结果显示

附:RISC-V 工具链


[1].Prebuilt RISC‑V GCC Toolchain

[2].elf2hex

SoC的Testbench中的简易bus_monitor(加入print函数)的更多相关文章

  1. python中print()函数的“,”与java中System.out.print()函数中的“+”

    python中的print()函数和java中的System.out.print()函数都有着打印字符串的功能. python中: print("hello,world!") 输出 ...

  2. Python中print函数输出时的左右对齐问题

    为了将print函数输出的内容对齐,笔者在http://www.jb51.net/article/55768.htm中找到了左右对齐的方法.整理如下: 一.数值类型(int.float) #  %d. ...

  3. CentOS 6中MATLAB print函数“所见非所得”bug的解决方案

    0 系统配置+软件版本 主机:Dell optiplex 390 MT (i5) 系统+软件:CentOS 6.5 x64, Matlab R2012, R2013 系统+软件:CentOS 6.7 ...

  4. MATLAB中白噪声的WGN和AWGN函数的使用

    MATLAB中白噪声的WGN和AWGN函数的使用如下: MATLAB中产生高斯白噪声非常方便,可以直接应用两个函数,一个是WGN,另一个是AWGN.WGN用于产生高斯白噪声,AWGN则用于在某一 信号 ...

  5. FastReport调用Delphi中的人民币大写转换自定义函数

    FastReport调用Delphi中的人民币大写转换自定义函数   FastReport调用Delphi中的人民币大写转换自定义函数 function TJzpzEdit1.MoneyCn(mmje ...

  6. Matlab中如何将(自定义)函数作为参数传递给另一个函数

    假如我们编写了一个积分通用程序,想使它更具有通用性,那么可以把被积函数也作为一个参数.在c/c++中,可以使用函数指针来实现上边的功能,在matlab中如何实现呢?使用函数句柄--这时类似于函数指针的 ...

  7. 【SAP BusinessObjects】WEBI中的动态求和,累加函数的使用

    在WEBI中,提供了这样一个函数: RunningSum([字段名]) 其作用是,将[字段名]这一列进行累加动态求和 对于需要进行计算累加值的列就不必写复杂的SQL,直接使用此函数即可解决.

  8. php中base64_decode与base64_encode加密解密函数

    php中base64_decode与base64_encode加密解密函数,实例分析了base64加密解密函数的具体用法,具有一定的实用价值,需要的朋友可以参考下 本文实例讲述了php中base64_ ...

  9. Linux 多线程应用中如何编写安全的信号处理函数

    http://blog.163.com/he_junwei/blog/static/1979376462014021105242552/ http://www.ibm.com/developerwor ...

随机推荐

  1. 66.app.use(express.static)

    转自:https://blog.csdn.net/u010977147/article/details/60956502

  2. 洛谷P2818 天使的起誓

    题目描述 Tenshi非常幸运地被选为掌管智慧之匙的天使.在正式任职之前,她必须和其他新当选的天使一样要宣誓.宣誓仪式是每位天使各自表述自己的使命,他们的发言稿放在n个呈圆形排列的宝盒中.这些宝盒按顺 ...

  3. ajax的内容

    ajax是什么? 通过在后台与服务器进行少量数据交换,Ajax 可以使网页实现异步更新,可以局部刷新而不必整个页面整体刷新. url的简单认识: 进入服务器的三种方式: 1.localhost:端口号 ...

  4. 【习题 8-14 UVA - 1616】Caravan Robbers

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 二分长度. 显然长度越长.就越不可能. 二分的时候.可以不用管精度. 直接指定一个二分次数的上限就好. 判断长度是否可行.直接用贪心 ...

  5. Myeclipse学习总结(3)——Myeclipse中的代码格式化、注释模板及保存时自动格式化

    设置Myeclipse中的代码格式化.注释模板及保存时自动格式化 1:设置注释的模板: 下载此模板:  codetemplates.xml This XML file does not appear ...

  6. JNDI学习总结(1)——JNDI入门

    JNDI是 Java 命名与目录接口(Java Naming and Directory Interface),在J2EE规范中是重要的规范之一,不少专家认为,没有透彻理解JNDI的意义和作用,就没有 ...

  7. PatentTips - Improving security in a virtual machine host

    BACKGROUND Computer viruses are a common problem for computer users. One typical mode of attack is t ...

  8. actionBar-进入界面闪烁问题解决

    问题分析: 主要是因为在开启一个应用的时候,当前界面并不是第一界面,在它之前,还有一个界面启动了,这个界面的唯一目的就是启动主界面,它目的不是显示.虽然如此,但是呢,这个界面的theme因为没有做统一 ...

  9. ORA-10458: standby database requires recovery

    搭建DG最后一步打开时报错如下:   SQL> alter database open read only; alter database open read only * ERROR at l ...

  10. BZOJ1023: [SHOI2008]cactus仙人掌图(仙人掌)

    Description 如果某个无向连通图的任意一条边至多只出现在一条简单回路(simple cycle)里,我们就称这张图为仙人掌图(cactus).所谓简单回路就是指在图上不重复经过任何一个顶点的 ...