C代碼調用printf時,打印信息顯示在哪個IO上,由pringf調用的底層代碼決定;軟件C中的printf默認在terminal上打印;對于嵌入式C, 運行在開發板上的code,可以借助target自己的顯示IO,如LCD屏,將打印信息直接顯示在LCD屏上;如果target沒有顯示IO,也可以retarget到host端的terminal上;simulation仿真時,運行的C代碼需要借助主機host的IO,將打印信息顯示在simulation terminal上;常見的方式有以下幾種:
仿照實際硬件操作,操作UART,GPIO等外設傳遞字符串,在平臺內監測外設接口,調用系統函數$display, $write等打印到terminal;構建tube實現打印,相比1效率更高;當仿真運行的不是RTL,而是FastModel時,可以借助semihost機制,利用IDE的界面打印;
完整的可運行代碼可以參考:
百度網盤鏈接:https://pan.baidu.com/s/13eKThizYnrKQzyUIkYhCPA
密碼:csdn
UART打印
struct __FILE { int handle
; };
FILE __stdout
;
FILE __stdin
;int fputc(int ch
, FILE
*f
) {return (UartPutc(ch
));
}
cmsdk_uart_capture_ard.v中捕獲字符串。
Tube打印
直接通過ahb/axi總線往reserved region寫數據,在平臺中監測并打印;
支持不定參數,需要調用<stdarg.h>;
#include <stdarg.h>
#include <stdint.h>#define write_addr(a,v) ((*(volatile uint32_t *)(a)) = (v))
#define read_addr(a) (*(volatile uint32_t *)(a))
#define TUBE_BASE_ADDR (0x2f000000)
#define sim_char(v) write_addr(TUBE_BASE_ADDR+4,v)
#define sim_dec(v) write_addr(TUBE_BASE_ADDR+8,v)
#define sim_hex(v) write_addr(TUBE_BASE_ADDR+12,v)
#define sim_bin(v) write_addr(TUBE_BASE_ADDR+16,v)#define SIM_INFO_TAG (0x5a5a0001)
#define SIM_WARNING_TAG (0x5a5a0002)
#define SIM_ERROR_TAG (0x5a5a0003)
#define SIM_FATAL_TAG (0x5a5a0004)
#define SIM_MSG_TAG (0x5a5a0005)
#define LF_VAL (10)
#define CR_VAL (13)
#define set_print_tag(v) write_addr(TUBE_BASE_ADDR+20,v)#define sim_event(v) write_addr(TUBE_BASE_ADDR+24,v)#define SV2C_HS_ADDR 0xfffc
#define wait_sv2c_event(FLAG,CLEAR) \
do { \if(sv2c_event[FLAG] == 0){ \while(read_addr(SV2C_HS_ADDR) != FLAG) \{ \delay(10); \} \} \if(CLEAR) \sv2c_event[FLAG] = 0; \else \sv2c_event[FLAG] = 1; \
} while(0)extern uint32_t sv2c_event
[10];
extern va_list
sim_print(va_list list
, char *format
,uint32_t tag
);
extern void sim_info(char* format
, ...);
extern void sim_warning(char* format
, ...);
extern void sim_error(char* format
, ...);
extern void sim_fatal(char* format
, ...);
#include "common.h"uint32_t sv2c_event
[10] = {0,0,0,0,0,0,0,0,0,0};va_list
sim_print(va_list list
, char *format
,uint32_t tag
)
{char *char_h
;__asm
volatile("cpsid i \t\n""cpsid f \t\n");set_print_tag(tag
);while(*format
!='\0'){if(*format
== '%'){format
++;switch(*format
){case 'd':sim_dec(va_arg(list
,int));break;case 'x':sim_hex(va_arg(list
,int));break;case 'h':sim_hex(va_arg(list
,int));break;case 'b':sim_bin(va_arg(list
,int));break;case 's':char_h
= va_arg(list
,char*);while(*char_h
!='\0'){sim_char(*char_h
);char_h
++;}break;}format
++;}else{sim_char(*format
);format
++;}}set_print_tag(SIM_MSG_TAG
);__asm
volatile("cpsie i \t\n""cpsie f \t\n");return list
;
}void sim_info(char* format
, ...)
{va_list list
;va_start(list
,format
);list
= sim_print(list
,format
,SIM_INFO_TAG
);va_end(list
);
}void sim_warning(char* format
, ...)
{va_list list
;va_start(list
,format
);list
= sim_print(list
,format
,SIM_WARNING_TAG
);va_end(list
);
}void sim_error(char* format
, ...)
{va_list list
;va_start(list
,format
);list
= sim_print(list
,format
,SIM_ERROR_TAG
);va_end(list
);
}void sim_fatal(char* format
, ...)
{va_list list
;va_start(list
,format
);list
= sim_print(list
,format
,SIM_FATAL_TAG
);va_end(list
);
}
C代碼調用sim_info sim_warning sim_error sim_fatal,UVM側相應使用UVM_INFO UVM_WARNING UVM_ERROR UVM_FATAL實現打印;
event_sync
C和UVM的事件同步,可以通過以下幾種方式:
CPU的中斷或者事件信號通過Tube組件實現
完整的可運行代碼可以參考:
百度網盤鏈接:https://pan.baidu.com/s/13eKThizYnrKQzyUIkYhCPA
密碼:csdn
總結
以上是生活随笔為你收集整理的C case和UVM TB的交互,tube_print, event_sync的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。