mirror of https://github.com/efabless/caravel.git
115 lines
6.3 KiB
Python
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
|
||
|
|