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. amaze ui各个模块简单说明

    amaze ui各个模块简单说明 导航添加依据 http://amazeui.org/css/  下面内容属学习笔记,如有理解偏差和错误请留言相告,感谢!* =(官网这块写的很详细) 一.基本样式 1 ...

  2. html的学习思维导图

  3. POJ 2458 DFS+判重

    题意: 思路: 搜+判重 嗯搞定 (听说有好多人用7个for写得-.) //By SiriusRen #include <bitset> #include <cstdio>0 ...

  4. Android RecyclerView滑动监听,判断是否滑动到了最后一个item

    项目中的需求,RecyclerView横向滑动列表,要有加载更多的功能,给RecyclerView设置一个滑动监听,在onScrolled方法中判断一下滑动方向,然后在onScrollStateCha ...

  5. OpenCV —— 矩阵和图像操作

    cvAbs , cvAbsDiff , cvAbsDiffS cvAdd , cvAddS , cvAddWeighted(可添加权重) #include <cv.h> #include ...

  6. IFC数据模式架构的四个概念层

    IFC模型体系结构由四个层次构成, 从下到上依次是 资源层(Resource Layer).核心层(Core Layer).交互层(Interoperability Layer).领域层(Domain ...

  7. VMware Vsphere 6.0安装部署 Vsphere ESXi安装

    Vsphere ESXi安装 ESXi作为虚拟化环境的Hypervisor层,负责将服务器虚拟成资源池,提供接口供管理组件调用,将下面的iso刻录成光盘或可启动U盘,安装在服务器裸机上: 下载地址请见 ...

  8. locate---查找文件

  9. 00079_增强for循环

    1.格式 /* * JDK1.5新特性,增强for循环 * JDK1.5版本后,出现新的接口 java.lang.Iterable * Collection开始继承Iterable * Iterabl ...

  10. 【hihocoder 1378】网络流二·最大流最小割定理

    [Link]:http://hihocoder.com/problemset/problem/1378 [Description] [Solution] 在求完最小割(最大流)之后; 可以在剩余网络中 ...