C case和UVM TB的交互,tube_print, event_sync

C代码调用printf时,打印信息显示在哪个IO上,由pringf调用的底层代码决定;软件C中的printf默认在terminal上打印;对于嵌入式C, 运行在开发板上的code,可以借助target自己的显示IO,如LCD屏,将打印信息直接显示在LCD屏上;如果target没有显示IO,也可以retarget到host端的terminal上;simulation仿真时,运行的C代码需要借助主机host的IO,将打印信息显示在simulation terminal上;常见的方式有以下几种:

  1. 仿照实际硬件操作,操作UART,GPIO等外设传递字符串,在平台内监测外设接口,调用系统函数$display, $write等打印到terminal;
  2. 构建tube实现打印,相比1效率更高;
  3. 当仿真运行的不是RTL,而是FastModel时,可以借助semihost机制,利用IDE的界面打印;

完整的可运行代码可以参考
百度网盘链接:https://pan.baidu.com/s/1_t2KNywKyMNO62w6b0y7Zw
密码:csdn

UART打印

// Retarget.c
// 对printf函数retarget处理
// 调用UartPutc(ch);

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>;
如果需要打印大量信息,建议对信息进行分类,中间通过类似查表法的方式来处理;

//common.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, ...);
// common.c
#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的事件同步,可以通过以下几种方式:

  1. CPU的中断或者事件信号
  2. 通过Tube组件实现

后仿,低功耗仿真需要做一些修改,示例代码还未添加!!!

完整的可运行代码可以参考:
百度网盘链接:https://pan.baidu.com/s/1_t2KNywKyMNO62w6b0y7Zw
密码:csdn

UVM中,do_print是一个用于自定义打印对象的函数。通过对do_print函数的扩展,可以实现对对象的特定属性或结构进行打印。根据引用,do_print函数可以通过使用uvm_printer来实现自定义打印。该函数可以打印自定义的变量或结构,并使用printer.print_generic函数打印这些信息。 但严格来说,也可以不使用uvm_printer来定义do_print函数。然而,这样做将无法使用uvm_printer的子类中定义的打印格式,如引用所述。在do_print函数中,可以通过调用super.do_print来继承父类的打印功能,并使用printer.print_xxx函数打印对象的各个属性。 另外,引用提到,在UVM中,通过调用do_print函数实现sprint功能。在某些情况下,UVM的默认打印功能可能无法满足我们的需求,比如对于多维数组或结构体的打印。因此,我们可以对UVM的sprint功能进行扩展,以使打印的log内容符合我们的预期。在扩展sprint功能时,可以根据需要自定义do_print函数,并使用printer.print_xxx函数打印自定义的变量或结构。 总结来说,UVM中的do_print函数是用于自定义打印对象的函数。可以通过扩展do_print函数,使用uvm_printer来实现自定义打印功能,并通过printer.print_xxx函数打印对象的属性。在某些情况下,可以通过扩展sprint功能来满足特定的打印需求。<span class="em">1</span><span class="em">2</span><span class="em">3</span><span class="em">4</span>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

劲仔小鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值