Guía de escritura de la plataforma de prueba de verificación SystemVerilog Capítulo VIII OOP Guía de habilidades avanzadas de programación orientada a objetos

8.1 Herencia
Cree una clase compleja para transacciones de bus que pueda inyectar errores y tenga un retraso variable.
Método 1: Use la composición, es decir, instanciar otro tipo de clase en la clase. A veces es difícil separar las funciones en partes separadas. Si usa composición, necesita crear diferentes clases para transacciones correctas e incorrectas, y la plataforma de prueba para la clase correcta debe reescribirse para manejar la clase de objetos incorrecta.
Método 2: use clases de extensión: cuando necesite agregar transacciones, cuantas menos modificaciones al código de prueba existente, mejor, por ejemplo, agregar inyección de errores.
La diferencia entre la clase de extensión y la síntesis de clase: la
clase de extensión resuelve y agrega nuevas transacciones; cuando se usa la síntesis de clase, es problemático modificar mucho el código.
Cómo usar: la
clase de extensión comparte las variables y subrutinas de la clase base.
1) Los métodos en la clase básica deben marcarse como virtuales para que puedan redefinirse en la clase extendida. Cuando la función en la clase de extensión es la misma que el nombre de la función en la clase base, la función en la clase base es llamada por el nombre super. El sistema Verilog no permite que super.super.new realice múltiples llamadas.
2) Si el constructor de la clase base new () tiene parámetros, entonces la clase de extensión debe tener un constructor y llamar al constructor de la clase base en la primera línea del constructor.
Ejemplo 8.3 Constructor con parámetros en clase extendida

class Basel;
	int var;
	function new(input int var);//带有参数的构造函数
		this.var=var;
	endfunction
endclass

class Extended extends Basel;
	function new(input int var); //需要参数
		super.new(var);//必须是new构造函数的第一行
		//构造函数的其它行为
	endfunction
endclass

3) La regla OOP establece que el identificador de la clase base también puede apuntar al objeto de la clase extendida.

8.2 Modo Blueprint (Blueprint)
1) Antecedentes: un generador simple que transfiere datos al controlador a través de un buzón.
Ejemplo 8.5 La clase de generador
// La clase de generador que usa el objeto Transacción
// El primer intento ... solo funcionalidad limitada

class Generator;
	mailbox gen2drv;
	Transaction tr;

	function new(input mailbox gen2drv);
		this.gen2drv=gen2drv;//this->类一级变量
	endfunction

	task run;
		forever begin
			tr=new();//创建事务
			assert(tr.randomize);//随机化
			gen2drv.put(tr);//送入驱动器
		end
	endtask

endclass

Hay un problema: este ejemplo crea un objeto de transacción dentro del bucle en lugar de fuera del bucle para evitar errores comunes de la plataforma de prueba.
New () se coloca fuera del bucle. La razón del error es que el identificador se coloca en el buzón, no el objeto. Todos los identificadores apuntan al mismo objeto. (1) La ejecución de la tarea crea una cosa y la aleatoriza inmediatamente, lo que significa que la transacción utiliza todas las restricciones predeterminadas. Para modificar, debe modificar la clase de transacción. (2) La extensión no se puede usar

Solución: separe la creación e inicialización de tr y use el modo blueprint.

Otra pregunta: si simplemente separa la creación y la inicialización, y las coloca fuera del ciclo, para evitar errores en la plataforma de prueba (P200), ¿cómo resolverlos? Cómo resolver el patrón de modelo

2) El concepto de modo plano
primero construye un plano de objeto (molde de metal), luego modifica sus restricciones, e incluso lo reemplaza con un objeto extendido.Al azar de este plano, obtiene el valor aleatorio que desea asignar; Enviar a la corriente abajo.
Blueprint: es un enlace que le permite cambiar el comportamiento de la clase del generador sin modificar su código de clase. Los objetos Blueprint se construyen en un lugar (new ()) y se usan en otro lugar (ejecución de la tarea).
Ejemplo 8.6
Generador de clases usando el modo blueprint ;
buzón gen2drv;
Blueprint de transacción;

	function new(input mailbox gen2drv);
		this.gen2drv=gen2drv;
		blueprint=new();
	endfunction

	task run;
		Transaction tr;
		forever begin
			assert(blueprint.randomize);//随机化
			tr=blueprint.copy();
			gen2drv.put(tr);//送入驱动器
		end
	endtask

endclass

3) Análisis comparativo de P200 y P221: el
modo de modelo importante , hay una función de copia más que el nuevo generador () en el campo de bucle.
Pregunta (1) Modo Blueprint, nuevo () fuera del bucle, solo hay un objeto y el buzón solo puede ser un identificador, ¿cómo resolver los errores comunes de la plataforma?
Porque la copia es la copia del objeto, no la copia del identificador. De esta manera, el modo plano tiene un solo identificador, pero después de la aleatorización, la copia es equivalente a crear muchos objetos en el reciclaje. La esencia de los errores comunes en la plataforma de prueba es que solo se crea un objeto. Esto evita problemas.
Pregunta (2) En el modo plano, debido a que solo hay un número de ID, luego, en el ciclo de ejecución de la tarea, se han emitido muchos datos, y estos tienen solo un número de ID.
Como la copia es una copia de un objeto, el número de identificación también aumentará en la copia. Cada dato enviado tiene su propio número de identificación.
4)
Para inyectar errores utilizando la transacción extendida , la transacción del objeto del plan debe cambiarse a Badtransaction (cambiar el plan). Esta operación debe completarse entre la creación y la operación del entorno. Nota: Todas las referencias badTr están en este archivo, por lo que no es necesario cambiar la clase de entorno o la clase de generador.

Env.build ();
Begin
Badtr bad = new ();
Env.gen.blueprint = bad;
End
Env.run
tiene como objetivo reemplazar un objeto con otro. Después de New (), todos son objetos. Asignar objetos a objetos. ¿Cuál es esta forma de escribir? ¿No es una copia? La esencia de la replicación es apuntar un identificador a un objeto.
Explicación: lo anterior es una copia del identificador. Asigne el identificador de clase de extensión incorrecto al plano de identificador de clase base, de modo que el identificador de clase base apunte al objeto de clase de extensión. Cuando se llama al siguiente código, apunta directamente a la clase de extensión incorrecta y cambia el plan.
La diferencia entre Env.new () y nev.build ()
Env.new () solo la función new ()
nev.build () es para cada módulo new (), y transmite algunos parámetros, a través de estos parámetros se conectará cada módulo del entorno, Levántate
8.3 Downcasting tipo y métodos virtuales

8.3.1 $ cast como
fondo de conversión de tipo hacia abajo : el identificador de clase base puede apuntar al objeto de clase extendida, no se requiere código adicional; el identificador de clase extendida apunta al objeto de clase base, generalmente saldrá mal, pero a veces es posible, siempre que la premisa sea El identificador de clase base apunta a uno de sus objetos de clase de extensión.
Función: cuando el identificador de la clase de extensión apunta al objeto de la clase base, use la función $ cast (). En el caso de ilegal, no compilará error, devolverá un 0.
$ castCuando se usa para tareas, systemverilog verificará que el tipo de objeto de origen y el tipo de objeto de destino no coincidan en tiempo de ejecución, e informará un error;
$ ElencoCuando se usa como una función, la verificación de tipo aún se realiza. Cuando no hay coincidencia, no se informa ningún error y la función devuelve 0.
1) El manejador de la clase base apunta al objeto de clase extendida-Ocurrencia: Modifique el plano sin cambiar demasiado código, agregue funcionalidad
Ejemplo 8.12 Copie un manejador de clase extendida en un manejador de clase base

Transaction tr;   //基类句柄
BadTr bad;        //扩展类句柄
bad = new();     //构建BadTr 扩展对象
tr = bad;         //基类句柄指向扩展类对象
$display(tr.src);//显示基类对象的变量成员
tr.display;        //调用的是扩展类的方法

2) El identificador de clase de extensión apunta a la ocurrencia de objeto de clase base: la función de copia de método virtual de clase base, la función de copia en su clase heredada
asigna el identificador de clase base al identificador de clase de extensión, de modo que el identificador de clase de extensión apunta al objeto de clase base, el compilador general Cometerá errores y no podrá ejecutarse, así que tenga mucho cuidado;Cuando solo el identificador de clase base apunta al objeto de clase extendida, cuando el identificador de clase extendida apunta al objeto de clase base, no se produce ningún error. Para detectar si el manejador de la clase base apunta a un objeto de extensión y no permite que el compilador informe un error, puede usar la función $ cast () para detectarlo.
¿Qué sucede cuando apunta un identificador de clase de extensión a un objeto de clase base?
Ejemplo 8.13 Copie un identificador de clase base en un identificador de clase extendida

 tr= new();            //创建一个基类 对象
 bad = tr;               //扩展类句柄指向基类句柄 ERROR:这一行不会被编译
 $display(bad.bad_crc);//基类对象不存在bad_crc成员

Se producirá el error anterior y no se pasará la compilación. Debido a que algunos atributos no existen en la clase base; pero no siempre es ilegal que el identificador de la clase de extensión apunte al identificador de la clase base (vea el código a continuación, es posible),Se permite cuando el identificador de la clase base apunta a un objeto de clase extendida.
Ejemplo 8.14 usando $ cast para copiar el identificador

Transcation tr; //基类句柄
BadTr bad,bad2; //扩展类句柄
Bad= new();//构建BadTr扩展对象
Tr = bad;   //基类句柄指向扩展类对象
 
//检查对象类型并拷贝。如果类型失配则在仿真时报错
//如果成功,bad2就指向tr所引用的对象
$cast(bad2,tr);      //扩展类句柄指向基类对象

//检查类型失配,如果类型失配,在仿真时也不会输出错误信息
if(!$cast(bad2,tr);
	$display(“cannot assign tr to bad2”);
$display(bad2.bad_crc);//原始对象中存在bad_crc成员

Tipo de identificador y diferencia de tipo de objeto (traducción imprecisa en el libro, tipo de identificador y objeto)
Comprensión personal:
Transacción tr; El tipo de identificador tr es el
tipo de identificador de transacción :
Tipo de objeto de palabra clave : Diferencia de tipo de miembros en la clase
8.3.2 Método virtual Y polimorfismo
Polimorfismo: el fenómeno de múltiples programas que usan un nombre común (polimorfismo).
Resolución de problemas polimórficos: un problema que enfrenta la construcción de computadoras. Cuando la memoria física es pequeña, el procesador puede direccionar un gran espacio de direcciones. En respuesta a este problema, se introdujo la memoria virtual.
La desventaja de la herencia del método virtual:
el método virtual se usa en la clase base, y la misma "firma" debe usarse en la clase de extensión. La subrutina virtual en la clase de extensión no puede agregar o eliminar parámetros, lo que significa que debe planificarse con anticipación.
8.5 Copia del objeto
1) Debido a que es una función virtual, el método de copia en la clase de extensión también debe ser del tipo de transacción, consistente con la clase base. Pero el tipo que se va a copiar es badtr, por lo que un nuevo
ejemplo de clase base de cosas malas 8.20 con función virtual de copia

Class transaction ;
	Rand bit[31:0] src,dst,data[8]; //变量
	Bit[31:0] crc;

	Virtual function transaction copy ();
		Copy   = new();
		Copy.src = s rc;
		Copy.dst = dst;
		Copy.data = data;
		Copy.crc  = crc;
	Endfunction
Endclass

Ejemplo 8.21 Clase de transacción extendida con función virtual de copia

Calss badtr extends transaction
	Rand bit bad_crc;
	Virtual function badtr copy(); //错误
	Virtual function transaction copy();
		Badtr bad;
		Bad = new();
		Bad.src = src; //复制数据域
		bad.dst = dst;
		bad.data = data;
		bad.crc = crc;
		Bad.bad_crc = bad_crc;
		Return bad;
	endfunction
endclass

2) Primera ruta de optimización:Cree una función independiente copy_data, de modo que cada clase solo sea responsable de copiar sus variables locales, es decir, la función de copia en la clase extendida usa super.copy_data (tr), en lugar de copiar las variables en la clase base. Se ha mejorado la reutilización del código.
Ejemplo 8.23 ​​Clase de transacción extendida usando la función copy_datd
$ cast (bad, tr); // El manejador de clase extendida apunta al manejador de clase base, y el tipo de manejador de clase base se convierte al caso de uso de clase extendida: debido a la función virtual, la función virtual debe estar en la herencia Los nombres y parámetros en la clase base también son consistentes. De esta manera, el parámetro de la función copy_data en la clase de extensión sigue siendo un tipo de transacción tr, de modo que el parámetro es el identificador de la clase base, pero la función copy_data es realmente un miembro de la clase de extensión, y el parámetro del identificador de la clase base debe asignarse al identificador de la clase de extensión. Se devuelven los datos del tipo badtr de clase extendida, por lo que debe usar $ cast (bad, tr).
Método de optimización dos: la subrutina de copia anterior creará un nuevo objeto, una forma de mejorar esEspecifique la dirección de almacenamiento del objeto de copia..
Ejemplo 8.24 clase base de transacción usando la función de copia

class Transaction;
	Virtual function transaction copy(transaction to =null);
		if(to == null)
			copy = new(); //创建新对象
		else
			copy = to;//或者使用现有对象
		copy_data(copy);
endfunction

8.6 Clases abstractas y métodos virtuales puros
Antecedentes: uno de los objetivos de la verificación es crear código compartido por múltiples proyectos.
Propósito: systemverilog tiene dos métodos para crear una clase base compartida: clase abstracta y método virtual puro
Clase virtual (clase abstracta): puede ampliarse pero no instanciarse directamente.
Función virtual pura: un prototipo de método sin una entidad, equivalente a una declaración.
Las clases extendidas a partir de clases abstractas solo se pueden instanciar cuando todos los métodos virtuales tienen entidades, y los métodos virtuales puros solo se pueden definir en clases abstractas.
En la clase abstracta, los métodos virtuales puros no tienen entidades, y los métodos virtuales no puros son mejores para no escribir entidades.
8.7
Antecedentes de devolución de llamada : El propósito de la plataforma de prueba: crear un entorno de verificación que pueda usarse en todas las pruebas sin ninguna modificación. La clave para esto es que la plataforma de prueba usa ganchos (¿qué son ganchos?) Ganchos, que inyectan código nuevo sin modificar la clase original. Usando el método virtual, también puede anular el método de la clase base en la clase de extensión, pero debe repetir todo el código del método original, y sus modificaciones se propagarán a todas sus clases de extensión.
Propósito: La devolución de llamada es un enlace para inyectar nuevo código sin modificar la clase original.
Implementación: la tarea de devolución de llamada se crea en la capa superior y se llama en el nivel más bajo, es decir, la unidad. De esta manera, el controlador no necesita conocer ninguna información sobre la prueba, solo necesita usar una clase común que se pueda extender en la prueba.
1) Use la devolución de llamada para inyectar interferencia
Un uso común de las devoluciones de llamada es inyectar interferencia, Como la introducción de un error o retraso. La siguiente plataforma de prueba utiliza objetos de devolución de llamada para descartar aleatoriamente paquetes de datos.
¿Cómo funciona la clase de extensión? Inyecte errores en la clase de devolución de llamada extendida, ¿cómo funciona en el controlador?
La clave es el papel de la cola de datos. Se utiliza en el controlador. La cola de datos de la
clase base de devolución de llamada es una clase abstracta. La inyección de error se agrega a la clase de devolución de llamada extendida, y la clase de controlador de unidad es la cola de datos de la clase base de devolución de llamada. En el entorno, el identificador de clase de extensión se deja entrar en la clase de controlador y se devuelve la cola de datos de la clase base.
Ejemplo 8.13 Usar devolución de llamada para prueba de inyección de error crear devolución de llamada de inyección de error

begin
	Driver_cbs_drop dcd = new();//创建错误注入的回调任务
	env.drv.cbs.push_back(dcd); // Put into driver放入驱动器队列
end

¿Cuál es la diferencia con la clase de extensión anterior?
En el código anterior, para agregar código a la clase de extensión, debe hacer que el identificador de la clase base apunte al identificador de la clase de extensión.
Clase de controlador:
cómo interpretar el siguiente código La
devolución de llamada también puede enviar datos al marcador o recopilar la cobertura de la función.
Ventajas: Es posible que haya pensado en colocar el marcador y el grupo de datos de cobertura funcional en un procesador de transacciones y conectarlo a la plataforma de prueba a través del buzón. Este es un método torpe por las siguientes razones: casi todos los componentes de la plataforma de prueba son pasivos y asíncronos. , El componente solo se activa cuando la plataforma de prueba le proporciona datos, y no pasará información activamente al procesador de transacciones descendente. Problema: 1) Tal procesador de transacciones que necesita monitorear múltiples buzones al mismo tiempo es complicado; 2) Puede recopilar datos en múltiples lugares, pero el procesador de transacciones está diseñado para manejar una única devolución de llamada de origen de datos

38 artículos originales publicados · Me gusta 29 · Visitas 10,000+

Supongo que te gusta

Origin blog.csdn.net/weixin_45270982/article/details/95910838
Recomendado
Clasificación