Para hacer compatible los programas desarrollados en Venus en nuestra implementación monociclo del RISC-V, sería muy útil el uso en nuestro RISC-V de instrucciones para cargar direcciones de memoria en registros, como puede ser la (load address) o li (load immediate).
Las instrucciones la y li son realmente pseudoinstrucciones. El compilador crea dos instrucciones para la (auipc + addi) y dos instrucciones para li (lui+addi). En los dos casos se hace uso de una instrucción de tipo U-Format (auipc y lui).
En este post, la idea es mostrar una sugerencia de implementación de estas instrucciones U-Format en nuestro RISC-V monociclo.
Instrucciones U-Format
Si nos fijamos en la estructura de una instrucciones U-Format vemos que tienen un registro destino y un inmediato de 20 bits
Para los otros formatos de instrucciones los inmediatos eran de 12 bits y por tanto no nos permiten cargar valores de 32 bits en los registros. Para resolver esto tenemos las instrucciones de tipo U-Format que permiten hacer escrituras en los 20 bits de mayor peso de los registros. De esta forma combinando instrucciones U-Format e I-Format podemos cargar valores de 32bits ({20bits,12bits}) en los registros (es lo que hace la y li).
La instrucción lui:
La instrucción lui realiza la siguiente operación:
rd={instr[31:12],12’d0}
Se puede implementar como una generación de inmediato y una suma de este inmediato con 32’d0. El resultado de la suma se guarda en el registro rd.
La instrucción auipc:
La instrucción auipc realiza la siguiente operación:
rd={instr[31:12],12’d0} +PC
Se puede implementar mediante la generación de un inmediato y una suma de este inmediato con el PC. El resultado de la suma se guarda en el registro rd.
Sugerencia de Implementación en el RISC-V
En la siguiente imagen sugiero una posible implementación:
En esta implementación lo cambios más importantes están en:
- Bloque de entrada de la ALU: Antes la ALU podía realizar operaciones entre Registro y Registro o entre Registro e inmediato. Ahora añadimos un multiplexor nuevo que nos permite realizar operaciones entre 0 e Inmediato y PC con Inmediato.
- Generador de Inmediato: Debemos añadir la opción de generación de inmediatos para instrucciones U-Format. Inmediato={instr[31:12],12’d0}
- Control:
- Debemos añadir la señal de control AuipcLui: Esta señal selecciona la fuente de entrada a la ALU. Cuando tenemos una instrucción Auipc entonces la señal AuipcLui=2’d0 para que la ALU opere con el PC; cuando tenemos una instrucción Lui entonces la señal AuipcLui=2’d1 para que la ALU tenga un 0 en una de sus entradas. En las instrucciones I-Format, R-Format, … AuipcLui=2’d2.
- ALUOp: ALUOp debe indicar a ALU control que la ALU siempre sume cuando tenemos una instrucción U-Format. Para esto podemos aprovechar el mismo ALUOp de las instrucciones sw y lw donde la ALU siempre suma.
One Comment
Ramón Aliaga
Hola,
Yo había pensado una implementación ligeramente distinta. Las diferencias serían:
– El multiplexor de AuipcLui tiene solo dos entradas: PC y Read_data_1. Es decir, no está la entrada 32’d0, y la señal AuipcLui es de 1 bit.
– La ALU implementa una instrucción adicional cuya salida es simplemente la primera entrada sin modificar (result = A). Habría que seleccionar esta instrucción con ALUOp / ALU control para la LUI.
Como veis, a menudo hay varias soluciones posibles para implementar un circuito, y en principio todas son buenas. Podéis usar cualquiera de ellas, u otras que no se nos hayan ocurrido.
Un saludo.