caravel/verilog/dv/cocotb/wb_models/housekeepingWB/housekeepingWB.py

115 lines
6.3 KiB
Python

import json
import cocotb
from cocotb.triggers import Timer, RisingEdge, ReadOnly
from cocotb_bus.monitors import Monitor
from cocotb.log import SimLogFormatter, SimTimeContextFilter
from cocotb.binary import BinaryValue
from math import ceil
from wb_models.housekeepingWB.HKmonitor import HKmonitor
from wb_models.housekeepingWB.HKSPImonitor import HKSPImonitor
from wb_models.housekeepingWB.HKSPImonitor import CSBmonitor
from wb_models.housekeepingWB.HK_models import HK_models
from cocotb_bus.scoreboard import Scoreboard
import logging
import fnmatch
import copy
from cocotb.result import TestFailure
from common import Macros
class HK_whiteBox:
def __init__(self,dut,loggers=False):
self.dut = dut
self.hk_hdl = dut.uut.housekeeping
# self.hkspi_hdl = dut.uut.housekeeping.hkspi
self.clk = self.dut.uut.mprj_clock
self.reset = self.dut.uut.resetb
self.logger = loggers
self.load_js()
self.setupModels()
self.Monitors()
cocotb.scheduler.add(self.reg_model_sb())
"""load json models"""
def load_js(self):
with open('wb_models/housekeepingWB/housekeepingIF.json') as f:
self.interface = json.load(f)
with open('wb_models/housekeepingWB/HK_regs.json') as f:
self.reg_model = json.load(f)
self.output_if = copy.deepcopy(self.interface['outputs'])
""""method to add the housekeeping monitors"""
def Monitors(self):
inputs = self.interface['inputs']
outputs = self.interface['outputs']
# wishbone
wishbone_mon_i = HKmonitor(f"HKinputsMonitorwishbone",self.hk_hdl,inputs['wishbone'],self.clk,self.reset,self.logger,callback=self.wb_models.wishbone_model)
wishbone_mon_o = HKmonitor(f"HKoutputsMonitorwishbone",self.hk_hdl,outputs['wishbone'],self.clk,self.reset,self.logger)
wishbone_sb = Scoreboard(SB_name("wishbone_sb"),fail_immediately=False)
wishbone_sb.add_interface(wishbone_mon_o, self.wb_models.exp_out_wb)
# system
system_mon_i = HKmonitor(f"HKinputsMonitorsystem",self.hk_hdl,inputs['system'],self.clk,self.reset,self.logger,callback=self.wb_models.system_model)
# UART
UART_mon_i = HKmonitor(f"HKinputsMonitorUART",self.hk_hdl,inputs['UART'],self.clk,self.reset,self.logger,callback=self.wb_models.UART_model)
UART_mon_o = HKmonitor(f"HKoutputsMonitorUART",self.hk_hdl,outputs['UART'],self.clk,self.reset,self.logger)
UART_sb = Scoreboard(SB_name("UART_sb"),fail_immediately=False)
UART_sb.add_interface(UART_mon_o, self.wb_models.exp_out_uart_rx)
# debug
debug_mon_i = HKmonitor(f"HKinputsMonitordebug",self.hk_hdl,inputs['debug'],self.clk,self.reset,self.logger,callback=self.wb_models.debug_model)
debug_mon_o = HKmonitor(f"HKoutputsMonitordebug",self.hk_hdl,outputs['debug'],self.clk,self.reset,self.logger)
debug_sb = Scoreboard(SB_name("debug_sb"),fail_immediately=False)
debug_sb.add_interface(debug_mon_o, self.wb_models.exp_out_debug)
# SPI
SPI_mon_i = HKSPImonitor(f"HKinputsMonitorSPI",self.hk_hdl,inputs['SPI'],self.clk,self.reset,self.logger,callback=self.wb_models.spi_model)
SPI_mon_o = HKSPImonitor(f"HKoutputsMonitorSPI",self.hk_hdl,outputs['SPI'],self.clk,self.reset,self.logger,input=False)
CSBmonitor(f"HKCSBmonitor",self.hk_hdl,outputs['SPI'],self.clk,self.reset,False,callback=self.wb_models.reset_spi_vals)
SPI_sb = Scoreboard(SB_name("SPI_sb"),fail_immediately=False)
SPI_sb.add_interface(SPI_mon_o, self.wb_models.exp_out_spi)
"""initialize all models needed"""
def setupModels(self):
with open('wb_models/housekeepingWB/HK_regs.json') as f:
self.reg_model = json.load(f)
self.wb_models = HK_models(self.reg_model,self.output_if,self.hk_hdl)
"""scoreboard for register model check the reg model with RTL every clock"""
async def reg_model_sb(self):
while True:
await RisingEdge(self.clk)
for key,memory_block in self.reg_model.items():
if fnmatch.fnmatch(key, "_*"):
continue
for reg_shift,reg in memory_block.items():
for field in reg:
if reg_shift == "base_addr":
continue
RTL_reg_name = field[1]
if RTL_reg_name == None:
cocotb.log.debug(f"[HK_whiteBox][reg_model_sb] register {field[1]} in {key} doesn't have a RTL register")
continue
if isinstance(field[1],list):
RTL_name = field[1][0]
first_index = int(field[1][1])
second_index= int(field[1][2])
if Macros['GL']:
if RTL_name in ["mfgr_id","prod_id","mask_rev","mgmt_gpio_data"]: continue #TODO: change with SDF only
if Macros['GL']:
if fnmatch.fnmatch (RTL_name,"gpio_configure*"): continue #TODO: update gpio_configure and mgmt_gpio_data to get each bit in the SDF case
RTL_reg_path = self.hk_hdl._id(RTL_name,False)
size = RTL_reg_path.value.n_bits-1
RTL_reg_val = RTL_reg_path.value[size-first_index:size-second_index]
else :
if field[1] in ["pwr_ctrl_out"]: continue #TODO: delete when reset value is spicified
RTL_reg_path = self.hk_hdl._id(field[1],False)
RTL_reg_val = RTL_reg_path.value
if (RTL_reg_val.integer != field[6]):
cocotb.log.error(f'[HK_whiteBox][reg_model_sb] mismatch in register {field[1]} in {key} expected val = {int(field[6])} actual val = {int(RTL_reg_val.binstr,2)} ' )
else:
cocotb.log.debug(f'[HK_whiteBox][reg_model_sb] match in register {field[1]} in {key} expected val = {field[6]} actual val = {RTL_reg_val.integer} ' )
class SB_name:
def __init__(self,name) -> None:
self._name=name