diff --git a/OSVVM/AlertLogPkg.vhd b/OSVVM/AlertLogPkg.vhd new file mode 100644 index 0000000..b67316c --- /dev/null +++ b/OSVVM/AlertLogPkg.vhd @@ -0,0 +1,3311 @@ +-- +-- File Name: AlertLogPkg.vhd +-- Design Unit Name: AlertLogPkg +-- Revision: STANDARD VERSION +-- +-- Maintainer: Jim Lewis email: jim@synthworks.com +-- Contributor(s): +-- Jim Lewis jim@synthworks.com +-- +-- +-- Description: +-- Alert handling and log filtering (verbosity control) +-- Alert handling provides a method to count failures, errors, and warnings +-- To accumlate counts, a data structure is created in a shared variable +-- It is of type AlertLogStructPType which is defined in AlertLogBasePkg +-- Log filtering provides verbosity control for logs (display or do not display) +-- AlertLogPkg provides a simplified interface to the shared variable +-- +-- +-- Developed for: +-- SynthWorks Design Inc. +-- VHDL Training Classes +-- 11898 SW 128th Ave. Tigard, Or 97223 +-- http://www.SynthWorks.com +-- +-- Revision History: +-- Date Version Description +-- 01/2015: 2015.01 Initial revision +-- 03/2015 2015.03 Added: AlertIfEqual, AlertIfNotEqual, AlertIfDiff, PathTail, +-- ReportNonZeroAlerts, ReadLogEnables +-- 05/2015 2015.06 Added IncAlertCount, AffirmIf +-- 07/2015 2016.01 Fixed AlertLogID issue with > 32 IDs +-- 02/2016 2016.02 Fixed IsLogEnableType (for PASSED), AffirmIf (to pass AlertLevel) +-- Created LocalInitialize +-- 05/2017 2017.05 AffirmIfEqual, AffirmIfDiff, +-- GetAffirmCount (deprecates GetAffirmCheckCount), IncAffirmCount (deprecates IncAffirmCheckCount), +-- IsAlertEnabled (alias), IsLogEnabled (alias) +-- +-- +-- Copyright (c) 2015 - 2017 by SynthWorks Design Inc. All rights reserved. +-- +-- Verbatim copies of this source file may be used and +-- distributed without restriction. +-- +-- This source file is free software; you can redistribute it +-- and/or modify it under the terms of the ARTISTIC License +-- as published by The Perl Foundation; either version 2.0 of +-- the License, or (at your option) any later version. +-- +-- This source is distributed in the hope that it will be +-- useful, but WITHOUT ANY WARRANTY; without even the implied +-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +-- PURPOSE. See the Artistic License for details. +-- +-- You should have received a copy of the license with this source. +-- If not download it from, +-- http://www.perlfoundation.org/artistic_license_2_0 +-- + + +use std.textio.all ; +use work.OsvvmGlobalPkg.all ; +use work.TranscriptPkg.all ; +use work.TextUtilPkg.all ; + +library IEEE ; +use ieee.std_logic_1164.all ; +use ieee.numeric_std.all ; + +package AlertLogPkg is + + subtype AlertLogIDType is integer ; + type AlertType is (FAILURE, ERROR, WARNING) ; -- NEVER + subtype AlertIndexType is AlertType range FAILURE to WARNING ; + type AlertCountType is array (AlertIndexType) of integer ; + type AlertEnableType is array(AlertIndexType) of boolean ; + type LogType is (ALWAYS, DEBUG, FINAL, INFO, PASSED) ; -- NEVER -- See function IsLogEnableType + subtype LogIndexType is LogType range DEBUG to PASSED ; + type LogEnableType is array (LogIndexType) of boolean ; + + constant ALERTLOG_BASE_ID : AlertLogIDType := 0 ; -- Careful as some code may assume this is 0. + constant ALERTLOG_DEFAULT_ID : AlertLogIDType := 1 ; + constant ALERT_DEFAULT_ID : AlertLogIDType := ALERTLOG_DEFAULT_ID ; + constant LOG_DEFAULT_ID : AlertLogIDType := ALERTLOG_DEFAULT_ID ; + constant OSVVM_ALERTLOG_ID : AlertLogIDType := 2 ; + constant OSVVM_SCOREBOARD_ALERTLOG_ID : AlertLogIDType := OSVVM_ALERTLOG_ID ; + -- NUM_PREDEFINED_AL_IDS intended to be local, but depends on others + -- constant NUM_PREDEFINED_AL_IDS : AlertLogIDType := OSVVM_SCOREBOARD_ALERTLOG_ID - ALERTLOG_BASE_ID ; -- Not including base + constant ALERTLOG_ID_NOT_FOUND : AlertLogIDType := -1 ; -- alternately integer'right + constant ALERTLOG_ID_NOT_ASSIGNED : AlertLogIDType := -1 ; + constant MIN_NUM_AL_IDS : AlertLogIDType := 32 ; -- Number IDs initially allocated + + alias AlertLogOptionsType is work.OsvvmGlobalPkg.OsvvmOptionsType ; + + ------------------------------------------------------------ + -- Alert always goes to the transcript file + procedure Alert( + AlertLogID : AlertLogIDType ; + Message : string ; + Level : AlertType := ERROR + ) ; + procedure Alert( Message : string ; Level : AlertType := ERROR ) ; + + ------------------------------------------------------------ + procedure IncAlertCount( -- A silent form of alert + AlertLogID : AlertLogIDType ; + Level : AlertType := ERROR + ) ; + procedure IncAlertCount( Level : AlertType := ERROR ) ; + + ------------------------------------------------------------ + -- Similar to assert, except condition is positive + procedure AlertIf( AlertLogID : AlertLogIDType ; condition : boolean ; Message : string ; Level : AlertType := ERROR ) ; + procedure AlertIf( condition : boolean ; Message : string ; Level : AlertType := ERROR ) ; + impure function AlertIf( AlertLogID : AlertLogIDType ; condition : boolean ; Message : string ; Level : AlertType := ERROR ) return boolean ; + impure function AlertIf( condition : boolean ; Message : string ; Level : AlertType := ERROR ) return boolean ; + + ------------------------------------------------------------ + -- Direct replacement for assert + procedure AlertIfNot( AlertLogID : AlertLogIDType ; condition : boolean ; Message : string ; Level : AlertType := ERROR ) ; + procedure AlertIfNot( condition : boolean ; Message : string ; Level : AlertType := ERROR ) ; + impure function AlertIfNot( AlertLogID : AlertLogIDType ; condition : boolean ; Message : string ; Level : AlertType := ERROR ) return boolean ; + impure function AlertIfNot( condition : boolean ; Message : string ; Level : AlertType := ERROR ) return boolean ; + + ------------------------------------------------------------ + -- overloading for common functionality + procedure AlertIfEqual( AlertLogID : AlertLogIDType ; L, R : std_logic ; Message : string ; Level : AlertType := ERROR ) ; + procedure AlertIfEqual( AlertLogID : AlertLogIDType ; L, R : std_logic_vector ; Message : string ; Level : AlertType := ERROR ) ; + procedure AlertIfEqual( AlertLogID : AlertLogIDType ; L, R : unsigned ; Message : string ; Level : AlertType := ERROR ) ; + procedure AlertIfEqual( AlertLogID : AlertLogIDType ; L, R : signed ; Message : string ; Level : AlertType := ERROR ) ; + procedure AlertIfEqual( AlertLogID : AlertLogIDType ; L, R : integer ; Message : string ; Level : AlertType := ERROR ) ; + procedure AlertIfEqual( AlertLogID : AlertLogIDType ; L, R : real ; Message : string ; Level : AlertType := ERROR ) ; + procedure AlertIfEqual( AlertLogID : AlertLogIDType ; L, R : character ; Message : string ; Level : AlertType := ERROR ) ; + procedure AlertIfEqual( AlertLogID : AlertLogIDType ; L, R : string ; Message : string ; Level : AlertType := ERROR ) ; + procedure AlertIfEqual( AlertLogID : AlertLogIDType ; L, R : time ; Message : string ; Level : AlertType := ERROR ) ; + + procedure AlertIfEqual( L, R : std_logic ; Message : string ; Level : AlertType := ERROR ) ; + procedure AlertIfEqual( L, R : std_logic_vector ; Message : string ; Level : AlertType := ERROR ) ; + procedure AlertIfEqual( L, R : unsigned ; Message : string ; Level : AlertType := ERROR ) ; + procedure AlertIfEqual( L, R : signed ; Message : string ; Level : AlertType := ERROR ) ; + procedure AlertIfEqual( L, R : integer ; Message : string ; Level : AlertType := ERROR ) ; + procedure AlertIfEqual( L, R : real ; Message : string ; Level : AlertType := ERROR ) ; + procedure AlertIfEqual( L, R : character ; Message : string ; Level : AlertType := ERROR ) ; + procedure AlertIfEqual( L, R : string ; Message : string ; Level : AlertType := ERROR ) ; + procedure AlertIfEqual( L, R : time ; Message : string ; Level : AlertType := ERROR ) ; + + procedure AlertIfNotEqual( AlertLogID : AlertLogIDType ; L, R : std_logic ; Message : string ; Level : AlertType := ERROR ) ; + procedure AlertIfNotEqual( AlertLogID : AlertLogIDType ; L, R : std_logic_vector ; Message : string ; Level : AlertType := ERROR ) ; + procedure AlertIfNotEqual( AlertLogID : AlertLogIDType ; L, R : unsigned ; Message : string ; Level : AlertType := ERROR ) ; + procedure AlertIfNotEqual( AlertLogID : AlertLogIDType ; L, R : signed ; Message : string ; Level : AlertType := ERROR ) ; + procedure AlertIfNotEqual( AlertLogID : AlertLogIDType ; L, R : integer ; Message : string ; Level : AlertType := ERROR ) ; + procedure AlertIfNotEqual( AlertLogID : AlertLogIDType ; L, R : real ; Message : string ; Level : AlertType := ERROR ) ; + procedure AlertIfNotEqual( AlertLogID : AlertLogIDType ; L, R : character ; Message : string ; Level : AlertType := ERROR ) ; + procedure AlertIfNotEqual( AlertLogID : AlertLogIDType ; L, R : string ; Message : string ; Level : AlertType := ERROR ) ; + procedure AlertIfNotEqual( AlertLogID : AlertLogIDType ; L, R : time ; Message : string ; Level : AlertType := ERROR ) ; + + procedure AlertIfNotEqual( L, R : std_logic ; Message : string ; Level : AlertType := ERROR ) ; + procedure AlertIfNotEqual( L, R : std_logic_vector ; Message : string ; Level : AlertType := ERROR ) ; + procedure AlertIfNotEqual( L, R : unsigned ; Message : string ; Level : AlertType := ERROR ) ; + procedure AlertIfNotEqual( L, R : signed ; Message : string ; Level : AlertType := ERROR ) ; + procedure AlertIfNotEqual( L, R : integer ; Message : string ; Level : AlertType := ERROR ) ; + procedure AlertIfNotEqual( L, R : real ; Message : string ; Level : AlertType := ERROR ) ; + procedure AlertIfNotEqual( L, R : character ; Message : string ; Level : AlertType := ERROR ) ; + procedure AlertIfNotEqual( L, R : string ; Message : string ; Level : AlertType := ERROR ) ; + procedure AlertIfNotEqual( L, R : time ; Message : string ; Level : AlertType := ERROR ) ; + + ------------------------------------------------------------ + -- Simple Diff for file comparisons + procedure AlertIfDiff (AlertLogID : AlertLogIDType ; Name1, Name2 : string; Message : string := "" ; Level : AlertType := ERROR ) ; + procedure AlertIfDiff (Name1, Name2 : string; Message : string := "" ; Level : AlertType := ERROR ) ; + procedure AlertIfDiff (AlertLogID : AlertLogIDType ; file File1, File2 : text; Message : string := "" ; Level : AlertType := ERROR ) ; + procedure AlertIfDiff (file File1, File2 : text; Message : string := "" ; Level : AlertType := ERROR ) ; + + ------------------------------------------------------------ + ------------------------------------------------------------ + ------------------------------------------------------------ + procedure AffirmIf( + ------------------------------------------------------------ + AlertLogID : AlertLogIDType ; + condition : boolean ; + ReceivedMessage : string ; + ExpectedMessage : string ; + Enable : boolean := FALSE -- override internal enable + ) ; + + procedure AffirmIf( condition : boolean ; ReceivedMessage, ExpectedMessage : string ; Enable : boolean := FALSE ) ; + impure function AffirmIf( AlertLogID : AlertLogIDType ; condition : boolean ; ReceivedMessage, ExpectedMessage : string ; Enable : boolean := FALSE ) return boolean ; + impure function AffirmIf( condition : boolean ; ReceivedMessage, ExpectedMessage : string ; Enable : boolean := FALSE ) return boolean ; + + procedure AffirmIf( + AlertLogID : AlertLogIDType ; + condition : boolean ; + Message : string ; + Enable : boolean := FALSE -- override internal enable + ) ; + + procedure AffirmIf(condition : boolean ; Message : string ; Enable : boolean := FALSE ) ; + impure function AffirmIf( AlertLogID : AlertLogIDType ; condition : boolean ; Message : string ; Enable : boolean := FALSE ) return boolean ; + impure function AffirmIf( condition : boolean ; Message : string ; Enable : boolean := FALSE ) return boolean ; + + ------------------------------------------------------------ + procedure AffirmIfNot( AlertLogID : AlertLogIDType ; condition : boolean ; ReceivedMessage, ExpectedMessage : string ; Enable : boolean := FALSE ) ; + procedure AffirmIfNot( condition : boolean ; ReceivedMessage, ExpectedMessage : string ; Enable : boolean := FALSE ) ; + impure function AffirmIfNot( AlertLogID : AlertLogIDType ; condition : boolean ; ReceivedMessage, ExpectedMessage : string ; Enable : boolean := FALSE ) return boolean ; + impure function AffirmIfNot( condition : boolean ; ReceivedMessage, ExpectedMessage : string ; Enable : boolean := FALSE ) return boolean ; + + ------------------------------------------------------------ + procedure AffirmIfNot( AlertLogID : AlertLogIDType ; condition : boolean ; Message : string ; Enable : boolean := FALSE ) ; + procedure AffirmIfNot( condition : boolean ; Message : string ; Enable : boolean := FALSE ) ; + impure function AffirmIfNot( AlertLogID : AlertLogIDType ; condition : boolean ; Message : string ; Enable : boolean := FALSE ) return boolean ; + impure function AffirmIfNot( condition : boolean ; Message : string ; Enable : boolean := FALSE ) return boolean ; + + ------------------------------------------------------------ + procedure AffirmPassed( AlertLogID : AlertLogIDType ; Message : string ; Enable : boolean := FALSE ) ; + procedure AffirmPassed( Message : string ; Enable : boolean := FALSE ) ; + procedure AffirmError( AlertLogID : AlertLogIDType ; Message : string ) ; + procedure AffirmError( Message : string ) ; + + ------------------------------------------------------------ + procedure AffirmIfEqual( AlertLogID : AlertLogIDType ; Received, Expected : std_logic ; Message : string := "" ; Enable : boolean := FALSE ) ; + procedure AffirmIfEqual( AlertLogID : AlertLogIDType ; Received, Expected : std_logic_vector ; Message : string := "" ; Enable : boolean := FALSE ) ; + procedure AffirmIfEqual( AlertLogID : AlertLogIDType ; Received, Expected : unsigned ; Message : string := "" ; Enable : boolean := FALSE ) ; + procedure AffirmIfEqual( AlertLogID : AlertLogIDType ; Received, Expected : signed ; Message : string := "" ; Enable : boolean := FALSE ); + procedure AffirmIfEqual( AlertLogID : AlertLogIDType ; Received, Expected : integer ; Message : string := "" ; Enable : boolean := FALSE ) ; + procedure AffirmIfEqual( AlertLogID : AlertLogIDType ; Received, Expected : real ; Message : string := "" ; Enable : boolean := FALSE ) ; + procedure AffirmIfEqual( AlertLogID : AlertLogIDType ; Received, Expected : character ; Message : string := "" ; Enable : boolean := FALSE ) ; + procedure AffirmIfEqual( AlertLogID : AlertLogIDType ; Received, Expected : string ; Message : string := "" ; Enable : boolean := FALSE ) ; + procedure AffirmIfEqual( AlertLogID : AlertLogIDType ; Received, Expected : time ; Message : string := "" ; Enable : boolean := FALSE ) ; + + -- Without AlertLogID + ------------------------------------------------------------ + procedure AffirmIfEqual( Received, Expected : std_logic ; Message : string := "" ; Enable : boolean := FALSE ) ; + procedure AffirmIfEqual( Received, Expected : std_logic_vector ; Message : string := "" ; Enable : boolean := FALSE ) ; + procedure AffirmIfEqual( Received, Expected : unsigned ; Message : string := "" ; Enable : boolean := FALSE ) ; + procedure AffirmIfEqual( Received, Expected : signed ; Message : string := "" ; Enable : boolean := FALSE ) ; + procedure AffirmIfEqual( Received, Expected : integer ; Message : string := "" ; Enable : boolean := FALSE ) ; + procedure AffirmIfEqual( Received, Expected : real ; Message : string := "" ; Enable : boolean := FALSE ) ; + procedure AffirmIfEqual( Received, Expected : character ; Message : string := "" ; Enable : boolean := FALSE ) ; + procedure AffirmIfEqual( Received, Expected : string ; Message : string := "" ; Enable : boolean := FALSE ) ; + procedure AffirmIfEqual( Received, Expected : time ; Message : string := "" ; Enable : boolean := FALSE ) ; + + ------------------------------------------------------------ + procedure AffirmIfDiff (AlertLogID : AlertLogIDType ; Name1, Name2 : string; Message : string := "" ; Enable : boolean := FALSE ) ; + procedure AffirmIfDiff (Name1, Name2 : string; Message : string := "" ; Enable : boolean := FALSE ) ; + procedure AffirmIfDiff (AlertLogID : AlertLogIDType ; file File1, File2 : text; Message : string := "" ; Enable : boolean := FALSE ) ; + procedure AffirmIfDiff (file File1, File2 : text; Message : string := "" ; Enable : boolean := FALSE ) ; + + ------------------------------------------------------------ + procedure SetAlertLogJustify ; + procedure ReportAlerts ( Name : String ; AlertCount : AlertCountType ) ; + procedure ReportAlerts ( Name : string := OSVVM_STRING_INIT_PARM_DETECT ; AlertLogID : AlertLogIDType := ALERTLOG_BASE_ID ; ExternalErrors : AlertCountType := (others => 0) ) ; + procedure ReportNonZeroAlerts ( Name : string := OSVVM_STRING_INIT_PARM_DETECT ; AlertLogID : AlertLogIDType := ALERTLOG_BASE_ID ; ExternalErrors : AlertCountType := (others => 0) ) ; + procedure ClearAlerts ; + function "ABS" (L : AlertCountType) return AlertCountType ; + function "+" (L, R : AlertCountType) return AlertCountType ; + function "-" (L, R : AlertCountType) return AlertCountType ; + function "-" (R : AlertCountType) return AlertCountType ; + impure function SumAlertCount(AlertCount: AlertCountType) return integer ; + impure function GetAlertCount(AlertLogID : AlertLogIDType := ALERTLOG_BASE_ID) return AlertCountType ; + impure function GetAlertCount(AlertLogID : AlertLogIDType := ALERTLOG_BASE_ID) return integer ; + impure function GetEnabledAlertCount(AlertLogID : AlertLogIDType := ALERTLOG_BASE_ID) return AlertCountType ; + impure function GetEnabledAlertCount(AlertLogID : AlertLogIDType := ALERTLOG_BASE_ID) return integer ; + impure function GetDisabledAlertCount return AlertCountType ; + impure function GetDisabledAlertCount return integer ; + impure function GetDisabledAlertCount(AlertLogID: AlertLogIDType) return AlertCountType ; + impure function GetDisabledAlertCount(AlertLogID: AlertLogIDType) return integer ; + + ------------------------------------------------------------ + -- log filtering for verbosity control, optionally has a separate file parameter + procedure Log( + AlertLogID : AlertLogIDType ; + Message : string ; + Level : LogType := ALWAYS ; + Enable : boolean := FALSE -- override internal enable + ) ; + procedure Log( Message : string ; Level : LogType := ALWAYS ; Enable : boolean := FALSE) ; + + ------------------------------------------------------------ + -- Accessor Methods + procedure SetAlertLogName(Name : string ) ; + impure function GetAlertLogName(AlertLogID : AlertLogIDType := ALERTLOG_BASE_ID) return string ; + procedure DeallocateAlertLogStruct ; + procedure InitializeAlertLogStruct ; + impure function FindAlertLogID(Name : string ) return AlertLogIDType ; + impure function FindAlertLogID(Name : string ; ParentID : AlertLogIDType) return AlertLogIDType ; + impure function GetAlertLogID(Name : string ; ParentID : AlertLogIDType := ALERTLOG_BASE_ID ; CreateHierarchy : Boolean := TRUE) return AlertLogIDType ; + impure function GetAlertLogParentID(AlertLogID : AlertLogIDType) return AlertLogIDType ; + + ------------------------------------------------------------ + -- Accessor Methods + procedure SetGlobalAlertEnable (A : boolean := TRUE) ; + impure function SetGlobalAlertEnable (A : boolean := TRUE) return boolean ; + impure function GetGlobalAlertEnable return boolean ; + procedure IncAffirmCount ; + impure function GetAffirmCount return natural ; +--?? procedure IncAffirmPassCount ; +--?? impure function GetAffirmPassCount return natural ; + + procedure SetAlertStopCount(AlertLogID : AlertLogIDType ; Level : AlertType ; Count : integer) ; + procedure SetAlertStopCount(Level : AlertType ; Count : integer) ; + impure function GetAlertStopCount(AlertLogID : AlertLogIDType ; Level : AlertType) return integer ; + impure function GetAlertStopCount(Level : AlertType) return integer ; + + procedure SetAlertEnable(Level : AlertType ; Enable : boolean) ; + procedure SetAlertEnable(AlertLogID : AlertLogIDType ; Level : AlertType ; Enable : boolean ; DescendHierarchy : boolean := TRUE) ; + impure function GetAlertEnable(AlertLogID : AlertLogIDType ; Level : AlertType) return boolean ; + impure function GetAlertEnable(Level : AlertType) return boolean ; + alias IsAlertEnabled is GetAlertEnable[AlertLogIDType, AlertType return boolean] ; + alias IsAlertEnabled is GetAlertEnable[AlertType return boolean] ; + + procedure SetLogEnable(Level : LogType ; Enable : boolean) ; + procedure SetLogEnable(AlertLogID : AlertLogIDType ; Level : LogType ; Enable : boolean ; DescendHierarchy : boolean := TRUE) ; + impure function GetLogEnable(AlertLogID : AlertLogIDType ; Level : LogType) return boolean ; + impure function GetLogEnable(Level : LogType) return boolean ; + alias IsLogEnabled is GetLogEnable [AlertLogIDType, LogType return boolean] ; -- same as GetLogEnable + alias IsLogEnabled is GetLogEnable [LogType return boolean] ; -- same as GetLogEnable + + procedure ReportLogEnables ; + + ------------------------------------------------------------ + procedure SetAlertLogOptions ( + FailOnWarning : AlertLogOptionsType := OPT_INIT_PARM_DETECT ; + FailOnDisabledErrors : AlertLogOptionsType := OPT_INIT_PARM_DETECT ; + ReportHierarchy : AlertLogOptionsType := OPT_INIT_PARM_DETECT ; + WriteAlertLevel : AlertLogOptionsType := OPT_INIT_PARM_DETECT ; + WriteAlertName : AlertLogOptionsType := OPT_INIT_PARM_DETECT ; + WriteAlertTime : AlertLogOptionsType := OPT_INIT_PARM_DETECT ; + WriteLogLevel : AlertLogOptionsType := OPT_INIT_PARM_DETECT ; + WriteLogName : AlertLogOptionsType := OPT_INIT_PARM_DETECT ; + WriteLogTime : AlertLogOptionsType := OPT_INIT_PARM_DETECT ; + AlertPrefix : string := OSVVM_STRING_INIT_PARM_DETECT ; + LogPrefix : string := OSVVM_STRING_INIT_PARM_DETECT ; + ReportPrefix : string := OSVVM_STRING_INIT_PARM_DETECT ; + DoneName : string := OSVVM_STRING_INIT_PARM_DETECT ; + PassName : string := OSVVM_STRING_INIT_PARM_DETECT ; + FailName : string := OSVVM_STRING_INIT_PARM_DETECT + ) ; + + procedure ReportAlertLogOptions ; + + impure function GetAlertLogFailOnWarning return AlertLogOptionsType ; + impure function GetAlertLogFailOnDisabledErrors return AlertLogOptionsType ; + impure function GetAlertLogReportHierarchy return AlertLogOptionsType ; + impure function GetAlertLogFoundReportHier return boolean ; + impure function GetAlertLogFoundAlertHier return boolean ; + impure function GetAlertLogWriteAlertLevel return AlertLogOptionsType ; + impure function GetAlertLogWriteAlertName return AlertLogOptionsType ; + impure function GetAlertLogWriteAlertTime return AlertLogOptionsType ; + impure function GetAlertLogWriteLogLevel return AlertLogOptionsType ; + impure function GetAlertLogWriteLogName return AlertLogOptionsType ; + impure function GetAlertLogWriteLogTime return AlertLogOptionsType ; + + impure function GetAlertLogAlertPrefix return string ; + impure function GetAlertLogLogPrefix return string ; + + impure function GetAlertLogReportPrefix return string ; + impure function GetAlertLogDoneName return string ; + impure function GetAlertLogPassName return string ; + impure function GetAlertLogFailName return string ; + + + -- File Reading Utilities + function IsLogEnableType (Name : String) return boolean ; + procedure ReadLogEnables (file AlertLogInitFile : text) ; + procedure ReadLogEnables (FileName : string) ; + + -- String Helper Functions -- This should be in a more general string package + function PathTail (A : string) return string ; + + + -- ------------------------------------------------------------ + -- Deprecated + -- + + -- deprecated + procedure AlertIf( condition : boolean ; AlertLogID : AlertLogIDType ; Message : string ; Level : AlertType := ERROR ) ; + impure function AlertIf( condition : boolean ; AlertLogID : AlertLogIDType ; Message : string ; Level : AlertType := ERROR ) return boolean ; + + -- deprecated + procedure AlertIfNot( condition : boolean ; AlertLogID : AlertLogIDType ; Message : string ; Level : AlertType := ERROR ) ; + impure function AlertIfNot( condition : boolean ; AlertLogID : AlertLogIDType ; Message : string ; Level : AlertType := ERROR ) return boolean ; + + -- deprecated + procedure AffirmIf( + AlertLogID : AlertLogIDType ; + condition : boolean ; + Message : string ; + LogLevel : LogType ; -- := PASSED + AlertLevel : AlertType := ERROR + ) ; + procedure AffirmIf( AlertLogID : AlertLogIDType ; condition : boolean ; Message : string ; AlertLevel : AlertType ) ; + procedure AffirmIf(condition : boolean ; Message : string ; LogLevel : LogType ; AlertLevel : AlertType := ERROR) ; + procedure AffirmIf(condition : boolean ; Message : string ; AlertLevel : AlertType ) ; + + alias IncAffirmCheckCount is IncAffirmCount [] ; + alias GetAffirmCheckCount is GetAffirmCount [return natural] ; + alias IsLoggingEnabled is GetLogEnable [AlertLogIDType, LogType return boolean] ; -- same as IsLogEnabled + alias IsLoggingEnabled is GetLogEnable [LogType return boolean] ; -- same as IsLogEnabled + + +end AlertLogPkg ; + +--- /////////////////////////////////////////////////////////////////////////// +--- /////////////////////////////////////////////////////////////////////////// +--- /////////////////////////////////////////////////////////////////////////// + +use work.NamePkg.all ; + +package body AlertLogPkg is + + -- instead of justify(to_upper(to_string())), just look up the upper case, left justified values + type AlertNameType is array(AlertType) of string(1 to 7) ; + constant ALERT_NAME : AlertNameType := (WARNING => "WARNING", ERROR => "ERROR ", FAILURE => "FAILURE") ; -- , NEVER => "NEVER " + type LogNameType is array(LogType) of string(1 to 7) ; + constant LOG_NAME : LogNameType := (DEBUG => "DEBUG ", FINAL => "FINAL ", INFO => "INFO ", ALWAYS => "ALWAYS ", PASSED => "PASSED ") ; -- , NEVER => "NEVER " + + + type AlertLogStructPType is protected + + ------------------------------------------------------------ + procedure alert ( + ------------------------------------------------------------ + AlertLogID : AlertLogIDType ; + message : string ; + level : AlertType := ERROR + ) ; + + ------------------------------------------------------------ + procedure IncAlertCount ( AlertLogID : AlertLogIDType ; level : AlertType := ERROR ) ; + procedure SetJustify ; + procedure ReportAlerts ( Name : string ; AlertCount : AlertCountType ) ; + procedure ReportAlerts ( Name : string := OSVVM_STRING_INIT_PARM_DETECT ; AlertLogID : AlertLogIDType := ALERTLOG_BASE_ID ; ExternalErrors : AlertCountType := (0,0,0) ; ReportAll : boolean := TRUE ) ; + procedure ClearAlerts ; + impure function GetAlertCount(AlertLogID : AlertLogIDType := ALERTLOG_BASE_ID) return AlertCountType ; + impure function GetEnabledAlertCount(AlertLogID : AlertLogIDType := ALERTLOG_BASE_ID) return AlertCountType ; + impure function GetDisabledAlertCount return AlertCountType ; + impure function GetDisabledAlertCount(AlertLogID: AlertLogIDType) return AlertCountType ; + + ------------------------------------------------------------ + procedure log ( + ------------------------------------------------------------ + AlertLogID : AlertLogIDType ; + Message : string ; + Level : LogType := ALWAYS ; + Enable : boolean := FALSE -- override internal enable + ) ; + + ------------------------------------------------------------ + -- FILE IO Controls +-- procedure SetTranscriptEnable (A : boolean := TRUE) ; +-- impure function IsTranscriptEnabled return boolean ; +-- procedure MirrorTranscript (A : boolean := TRUE) ; +-- impure function IsTranscriptMirrored return boolean ; + + ------------------------------------------------------------ + ------------------------------------------------------------ + -- AlertLog Structure Creation and Interaction Methods + + ------------------------------------------------------------ + procedure SetAlertLogName(Name : string ) ; + procedure SetNumAlertLogIDs (NewNumAlertLogIDs : integer) ; + impure function FindAlertLogID(Name : string ) return AlertLogIDType ; + impure function FindAlertLogID(Name : string ; ParentID : AlertLogIDType) return AlertLogIDType ; + impure function GetAlertLogID(Name : string ; ParentID : AlertLogIDType ; CreateHierarchy : Boolean) return AlertLogIDType ; + impure function GetAlertLogParentID(AlertLogID : AlertLogIDType) return AlertLogIDType ; + procedure Initialize(NewNumAlertLogIDs : integer := MIN_NUM_AL_IDS) ; + procedure Deallocate ; + + ------------------------------------------------------------ + ------------------------------------------------------------ + -- Accessor Methods + ------------------------------------------------------------ + procedure SetGlobalAlertEnable (A : boolean := TRUE) ; + impure function GetAlertLogName(AlertLogID : AlertLogIDType) return string ; + impure function GetGlobalAlertEnable return boolean ; + procedure IncAffirmCount ; + impure function GetAffirmCount return natural ; +--?? procedure IncAffirmPassCount ; +--?? impure function GetAffirmPassCount return natural ; + + procedure SetAlertStopCount(AlertLogID : AlertLogIDType ; Level : AlertType ; Count : integer) ; + impure function GetAlertStopCount(AlertLogID : AlertLogIDType ; Level : AlertType) return integer ; + + procedure SetAlertEnable(Level : AlertType ; Enable : boolean) ; + procedure SetAlertEnable(AlertLogID : AlertLogIDType ; Level : AlertType ; Enable : boolean ; DescendHierarchy : boolean := TRUE) ; + impure function GetAlertEnable(AlertLogID : AlertLogIDType ; Level : AlertType) return boolean ; + + procedure SetLogEnable(Level : LogType ; Enable : boolean) ; + procedure SetLogEnable(AlertLogID : AlertLogIDType ; Level : LogType ; Enable : boolean ; DescendHierarchy : boolean := TRUE) ; + impure function GetLogEnable(AlertLogID : AlertLogIDType ; Level : LogType) return boolean ; + + procedure ReportLogEnables ; + + ------------------------------------------------------------ + -- Reporting Accessor + procedure SetAlertLogOptions ( + FailOnWarning : AlertLogOptionsType := OPT_INIT_PARM_DETECT ; + FailOnDisabledErrors : AlertLogOptionsType := OPT_INIT_PARM_DETECT ; + ReportHierarchy : AlertLogOptionsType := OPT_INIT_PARM_DETECT ; + WriteAlertLevel : AlertLogOptionsType := OPT_INIT_PARM_DETECT ; + WriteAlertName : AlertLogOptionsType := OPT_INIT_PARM_DETECT ; + WriteAlertTime : AlertLogOptionsType := OPT_INIT_PARM_DETECT ; + WriteLogLevel : AlertLogOptionsType := OPT_INIT_PARM_DETECT ; + WriteLogName : AlertLogOptionsType := OPT_INIT_PARM_DETECT ; + WriteLogTime : AlertLogOptionsType := OPT_INIT_PARM_DETECT ; + AlertPrefix : string := OSVVM_STRING_INIT_PARM_DETECT ; + LogPrefix : string := OSVVM_STRING_INIT_PARM_DETECT ; + ReportPrefix : string := OSVVM_STRING_INIT_PARM_DETECT ; + DoneName : string := OSVVM_STRING_INIT_PARM_DETECT ; + PassName : string := OSVVM_STRING_INIT_PARM_DETECT ; + FailName : string := OSVVM_STRING_INIT_PARM_DETECT + ) ; + procedure ReportAlertLogOptions ; + + impure function GetAlertLogFailOnWarning return AlertLogOptionsType ; + impure function GetAlertLogFailOnDisabledErrors return AlertLogOptionsType ; + impure function GetAlertLogReportHierarchy return AlertLogOptionsType ; + impure function GetAlertLogFoundReportHier return boolean ; + impure function GetAlertLogFoundAlertHier return boolean ; + impure function GetAlertLogWriteAlertLevel return AlertLogOptionsType ; + impure function GetAlertLogWriteAlertName return AlertLogOptionsType ; + impure function GetAlertLogWriteAlertTime return AlertLogOptionsType ; + impure function GetAlertLogWriteLogLevel return AlertLogOptionsType ; + impure function GetAlertLogWriteLogName return AlertLogOptionsType ; + impure function GetAlertLogWriteLogTime return AlertLogOptionsType ; + + impure function GetAlertLogAlertPrefix return string ; + impure function GetAlertLogLogPrefix return string ; + + impure function GetAlertLogReportPrefix return string ; + impure function GetAlertLogDoneName return string ; + impure function GetAlertLogPassName return string ; + impure function GetAlertLogFailName return string ; + + end protected AlertLogStructPType ; + + --- /////////////////////////////////////////////////////////////////////////// + + type AlertLogStructPType is protected body + + variable GlobalAlertEnabledVar : boolean := TRUE ; -- Allows turn off and on + + variable AffirmCheckCountVar : natural := 0 ; +--?? variable AffirmPassedCountVar : natural := 0 ; + + ------------------------------------------------------------ + type AlertLogRecType is record + ------------------------------------------------------------ + Name : Line ; + ParentID : AlertLogIDType ; + AlertCount : AlertCountType ; + AlertStopCount : AlertCountType ; + AlertEnabled : AlertEnableType ; + LogEnabled : LogEnableType ; + end record AlertLogRecType ; + + ------------------------------------------------------------ + -- Basis for AlertLog Data Structure + variable NumAlertLogIDsVar : AlertLogIDType := 0 ; -- defined by initialize + variable NumAllocatedAlertLogIDsVar : AlertLogIDType := 0 ; +--xx variable NumPredefinedAlIDsVar : AlertLogIDType := 0 ; -- defined by initialize + + type AlertLogRecPtrType is access AlertLogRecType ; + type AlertLogArrayType is array (AlertLogIDType range <>) of AlertLogRecPtrType ; + type AlertLogArrayPtrType is access AlertLogArrayType ; + variable AlertLogPtr : AlertLogArrayPtrType ; + + ------------------------------------------------------------ + -- Report formatting settings, with defaults + variable FailOnWarningVar : boolean := TRUE ; + variable FailOnDisabledErrorsVar : boolean := TRUE ; + variable ReportHierarchyVar : boolean := TRUE ; + variable FoundReportHierVar : boolean := FALSE ; + variable FoundAlertHierVar : boolean := FALSE ; + + variable WriteAlertLevelVar : boolean := TRUE ; + variable WriteAlertNameVar : boolean := TRUE ; + variable WriteAlertTimeVar : boolean := TRUE ; + variable WriteLogLevelVar : boolean := TRUE ; + variable WriteLogNameVar : boolean := TRUE ; + variable WriteLogTimeVar : boolean := TRUE ; + + variable AlertPrefixVar : NamePType ; + variable LogPrefixVar : NamePType ; + variable ReportPrefixVar : NamePType ; + variable DoneNameVar : NamePType ; + variable PassNameVar : NamePType ; + variable FailNameVar : NamePType ; + + variable AlertLogJustifyAmountVar : integer := 0 ; + variable ReportJustifyAmountVar : integer := 0 ; + + ------------------------------------------------------------ + -- PT Local + impure function LeftJustify(A : String; Amount : integer) return string is + ------------------------------------------------------------ + constant Spaces : string(1 to maximum(1, Amount)) := (others => ' ') ; + begin + if A'length >= Amount then + return A ; + else + return A & Spaces(1 to Amount - A'length) ; + end if ; + end function LeftJustify ; + + + ------------------------------------------------------------ + -- PT Local + procedure IncrementAlertCount( + ------------------------------------------------------------ + constant AlertLogID : in AlertLogIDType ; + constant Level : in AlertType ; + variable StopDueToCount : inout boolean + ) is + begin + -- Always Count at this level + AlertLogPtr(AlertLogID).AlertCount(Level) := AlertLogPtr(AlertLogID).AlertCount(Level) + 1 ; + -- Only do remaining actions if enabled + if AlertLogPtr(AlertLogID).AlertEnabled(Level) then + -- Exceeded Stop Count at this level? + if AlertLogPtr(AlertLogID).AlertCount(Level) >= AlertLogPtr(AlertLogID).AlertStopCount(Level) then + StopDueToCount := TRUE ; + end if ; + -- Propagate counts to parent(s) -- Ascend Hierarchy + if AlertLogID /= ALERTLOG_BASE_ID then + IncrementAlertCount(AlertLogPtr(AlertLogID).ParentID, Level, StopDueToCount) ; + end if ; + end if ; + end procedure IncrementAlertCount ; + + ------------------------------------------------------------ + procedure alert ( + ------------------------------------------------------------ + AlertLogID : AlertLogIDType ; + message : string ; + level : AlertType := ERROR + ) is + variable buf : Line ; + constant AlertPrefix : string := AlertPrefixVar.Get(OSVVM_DEFAULT_ALERT_PREFIX) ; + variable StopDueToCount : boolean := FALSE ; + begin + if GlobalAlertEnabledVar then + -- Do not write or count when GlobalAlertEnabledVar is disabled + if AlertLogPtr(AlertLogID).AlertEnabled(Level) then + -- do not write when disabled + write(buf, AlertPrefix) ; + if WriteAlertLevelVar then + -- write(buf, " " & to_string(Level) ) ; + write(buf, " " & ALERT_NAME(Level)) ; -- uses constant lookup + end if ; +--xx if (NumAlertLogIDsVar > NumPredefinedAlIDsVar) and WriteAlertNameVar then -- print hierarchy names even when silent + if FoundAlertHierVar and WriteAlertNameVar then +-- write(buf, " in " & justify(AlertLogPtr(AlertLogID).Name.all & ",", LEFT, AlertLogJustifyAmountVar) ) ; + write(buf, " in " & LeftJustify(AlertLogPtr(AlertLogID).Name.all & ",", AlertLogJustifyAmountVar) ) ; + end if ; + write(buf, " " & Message) ; + if WriteAlertTimeVar then + write(buf, " at " & to_string(NOW, 1 ns)) ; + end if ; + writeline(buf) ; + end if ; + -- Always Count + IncrementAlertCount(AlertLogID, Level, StopDueToCount) ; + if StopDueToCount then + write(buf, LF & AlertPrefix & " Stop Count on " & ALERT_NAME(Level) & " reached") ; +--xx if NumAlertLogIDsVar > NumPredefinedAlIDsVar then -- print hierarchy names even when silent + if FoundAlertHierVar then + write(buf, " in " & AlertLogPtr(AlertLogID).Name.all) ; + end if ; + write(buf, " at " & to_string(NOW, 1 ns) & " ") ; + writeline(buf) ; + ReportAlerts(ReportAll => TRUE) ; + std.env.stop(1) ; + end if ; + end if ; + end procedure alert ; + + ------------------------------------------------------------ + procedure IncAlertCount ( + ------------------------------------------------------------ + AlertLogID : AlertLogIDType ; + level : AlertType := ERROR + ) is + variable buf : Line ; + constant AlertPrefix : string := AlertPrefixVar.Get(OSVVM_DEFAULT_ALERT_PREFIX) ; + variable StopDueToCount : boolean := FALSE ; + begin + if GlobalAlertEnabledVar then + IncrementAlertCount(AlertLogID, Level, StopDueToCount) ; + if StopDueToCount then + write(buf, LF & AlertPrefix & " Stop Count on " & ALERT_NAME(Level) & " reached") ; +--xx if NumAlertLogIDsVar > NumPredefinedAlIDsVar then -- print hierarchy names even when silent + if FoundAlertHierVar then + write(buf, " in " & AlertLogPtr(AlertLogID).Name.all) ; + end if ; + write(buf, " at " & to_string(NOW, 1 ns) & " ") ; + writeline(buf) ; + ReportAlerts(ReportAll => TRUE) ; + std.env.stop ; + end if ; + end if ; + end procedure IncAlertCount ; + + ------------------------------------------------------------ + -- PT Local + impure function CalcJustify (AlertLogID : AlertLogIDType ; CurrentLength : integer ; IndentAmount : integer) return integer_vector is + ------------------------------------------------------------ + variable ResultValues, LowerLevelValues : integer_vector(1 to 2) ; -- 1 = Max, 2 = Indented + begin + ResultValues(1) := CurrentLength + 1 ; -- AlertLogJustifyAmountVar + ResultValues(2) := CurrentLength + IndentAmount ; -- ReportJustifyAmountVar + for i in AlertLogID+1 to NumAlertLogIDsVar loop + if AlertLogID = AlertLogPtr(i).ParentID then + LowerLevelValues := CalcJustify(i, AlertLogPtr(i).Name'length, IndentAmount + 2) ; + ResultValues(1) := maximum(ResultValues(1), LowerLevelValues(1)) ; + ResultValues(2) := maximum(ResultValues(2), LowerLevelValues(2)) ; + end if ; + end loop ; + return ResultValues ; + end function CalcJustify ; + + ------------------------------------------------------------ + procedure SetJustify is + ------------------------------------------------------------ + variable ResultValues : integer_vector(1 to 2) ; -- 1 = Max, 2 = Indented + begin + ResultValues := CalcJustify(ALERTLOG_BASE_ID, 0, 0) ; + AlertLogJustifyAmountVar := ResultValues(1) ; + ReportJustifyAmountVar := ResultValues(2) ; + end procedure SetJustify ; + + ------------------------------------------------------------ + -- PT Local + impure function GetEnabledAlertCount(AlertCount: AlertCountType; AlertEnabled : AlertEnableType) return AlertCountType is + ------------------------------------------------------------ + variable Count : AlertCountType := (others => 0) ; + begin + if AlertEnabled(FAILURE) then + Count(FAILURE) := AlertCount(FAILURE) ; + end if ; + if AlertEnabled(ERROR) then + Count(ERROR) := AlertCount(ERROR) ; + end if ; + if FailOnWarningVar and AlertEnabled(WARNING) then + Count(WARNING) := AlertCount(WARNING) ; + end if ; + return Count ; + end function GetEnabledAlertCount ; + + ------------------------------------------------------------ + impure function GetAlertCount(AlertLogID : AlertLogIDType := ALERTLOG_BASE_ID) return AlertCountType is + ------------------------------------------------------------ + variable AlertCount : AlertCountType ; + begin + return AlertLogPtr(AlertLogID).AlertCount ; + end function GetAlertCount ; + + ------------------------------------------------------------ + impure function GetEnabledAlertCount(AlertLogID : AlertLogIDType := ALERTLOG_BASE_ID) return AlertCountType is + ------------------------------------------------------------ + variable AlertCount : AlertCountType ; + begin + return GetEnabledAlertCount(AlertLogPtr(AlertLogID).AlertCount, AlertLogPtr(AlertLogID).AlertEnabled) ; + end function GetEnabledAlertCount ; + + ------------------------------------------------------------ + -- PT Local + impure function GetDisabledAlertCount(AlertCount: AlertCountType; AlertEnabled : AlertEnableType) return AlertCountType is + ------------------------------------------------------------ + variable Count : AlertCountType := (others => 0) ; + begin + if not AlertEnabled(FAILURE) then + Count(FAILURE) := AlertCount(FAILURE) ; + end if ; + if not AlertEnabled(ERROR) then + Count(ERROR) := AlertCount(ERROR) ; + end if ; + if FailOnWarningVar and not AlertEnabled(WARNING) then + Count(WARNING) := AlertCount(WARNING) ; + end if ; + return Count ; + end function GetDisabledAlertCount ; + + ------------------------------------------------------------ + impure function GetDisabledAlertCount return AlertCountType is + ------------------------------------------------------------ + variable Count : AlertCountType := (others => 0) ; + begin + for i in ALERTLOG_BASE_ID to NumAlertLogIDsVar loop + Count := Count + GetDisabledAlertCount(AlertLogPtr(i).AlertCount, AlertLogPtr(i).AlertEnabled) ; + end loop ; + return Count ; + end function GetDisabledAlertCount ; + + ------------------------------------------------------------ + impure function GetDisabledAlertCount(AlertLogID: AlertLogIDType) return AlertCountType is + ------------------------------------------------------------ + variable Count : AlertCountType := (others => 0) ; + begin + Count := GetDisabledAlertCount(AlertLogPtr(AlertLogID).AlertCount, AlertLogPtr(AlertLogID).AlertEnabled) ; + for i in AlertLogID+1 to NumAlertLogIDsVar loop + if AlertLogID = AlertLogPtr(i).ParentID then + Count := Count + GetDisabledAlertCount(i) ; + end if ; + end loop ; + return Count ; + end function GetDisabledAlertCount ; + + ------------------------------------------------------------ + -- PT Local + procedure PrintTopAlerts ( + ------------------------------------------------------------ + NumErrors : integer ; + AlertCount : AlertCountType ; + Name : string ; + NumDisabledErrors : integer + ) is + constant ReportPrefix : string := ResolveOsvvmWritePrefix(ReportPrefixVar.GetOpt ) ; + constant DoneName : string := ResolveOsvvmDoneName(DoneNameVar.GetOpt ) ; + constant PassName : string := ResolveOsvvmPassName(PassNameVar.GetOpt ) ; + constant FailName : string := ResolveOsvvmFailName(FailNameVar.GetOpt ) ; + variable buf : line ; + begin + if NumErrors = 0 then + if NumDisabledErrors = 0 then + -- Passed + write(buf, ReportPrefix & DoneName & " " & PassName & " " & Name) ; + if AffirmCheckCountVar > 0 then + write(buf, " Affirmations Checked: " & to_string(AffirmCheckCountVar)) ; + end if ; + write(buf, " at " & to_string(NOW, 1 ns)) ; + WriteLine(buf) ; + else + -- Failed Due to Disabled Errors + write(buf, ReportPrefix & DoneName & " " & FailName & " " & Name) ; + write(buf, " Failed Due to Disabled Error(s) = " & to_string(NumDisabledErrors)) ; + if AffirmCheckCountVar > 0 then + write(buf, " Affirmations Checked: " & to_string(AffirmCheckCountVar)) ; + end if ; + write(buf, " at " & to_string(NOW, 1 ns)) ; + WriteLine(buf) ; + end if ; + else + -- Failed + write(buf, ReportPrefix & DoneName & " " & FailName & " "& Name) ; + write(buf, " Total Error(s) = " & to_string(NumErrors) ) ; + write(buf, " Failures: " & to_string(AlertCount(FAILURE)) ) ; + write(buf, " Errors: " & to_string(AlertCount(ERROR) ) ) ; + write(buf, " Warnings: " & to_string(AlertCount(WARNING) ) ) ; + if AffirmCheckCountVar > 0 then +--?? write(buf, " Affirmations Passed: " & to_string(AffirmPassedCountVar)) ; +--?? write(buf, " Checked: " & to_string(AffirmCheckCountVar)) ; + write(buf, " Affirmations Checked: " & to_string(AffirmCheckCountVar)) ; + end if ; + Write(buf, " at " & to_string(NOW, 1 ns)) ; + WriteLine(buf) ; + end if ; + end procedure PrintTopAlerts ; + + ------------------------------------------------------------ + -- PT Local + procedure PrintChild( + ------------------------------------------------------------ + AlertLogID : AlertLogIDType ; + Prefix : string ; + IndentAmount : integer ; + ReportAll : boolean + ) is + variable buf : line ; + begin + for i in AlertLogID+1 to NumAlertLogIDsVar loop + if AlertLogID = AlertLogPtr(i).ParentID then + if ReportAll or SumAlertCount(AlertLogPtr(i).AlertCount) > 0 then + Write(buf, Prefix & " " & LeftJustify(AlertLogPtr(i).Name.all, ReportJustifyAmountVar - IndentAmount)) ; + write(buf, " Failures: " & to_string(AlertLogPtr(i).AlertCount(FAILURE) ) ) ; + write(buf, " Errors: " & to_string(AlertLogPtr(i).AlertCount(ERROR) ) ) ; + write(buf, " Warnings: " & to_string(AlertLogPtr(i).AlertCount(WARNING) ) ) ; + WriteLine(buf) ; + end if ; + PrintChild( + AlertLogID => i, + Prefix => Prefix & " ", + IndentAmount => IndentAmount + 2, + ReportAll => ReportAll + ) ; + end if ; + end loop ; + end procedure PrintChild ; + + ------------------------------------------------------------ + procedure ReportAlerts ( Name : string := OSVVM_STRING_INIT_PARM_DETECT ; AlertLogID : AlertLogIDType := ALERTLOG_BASE_ID ; ExternalErrors : AlertCountType := (0,0,0) ; ReportAll : boolean := TRUE) is + ------------------------------------------------------------ + variable NumErrors : integer ; + variable NumDisabledErrors : integer ; + constant ReportPrefix : string := ResolveOsvvmWritePrefix(ReportPrefixVar.GetOpt) ; + begin + if ReportJustifyAmountVar <= 0 then + SetJustify ; + end if ; + NumErrors := SumAlertCount( ExternalErrors + GetEnabledAlertCount(AlertLogPtr(AlertLogID).AlertCount, AlertLogPtr(AlertLogID).AlertEnabled) ) ; + if FailOnDisabledErrorsVar then + NumDisabledErrors := SumAlertCount( GetDisabledAlertCount(AlertLogID) ) ; + else + NumDisabledErrors := 0 ; + end if ; + if IsOsvvmStringSet(Name) then + PrintTopAlerts ( + NumErrors => NumErrors, + AlertCount => AlertLogPtr(AlertLogID).AlertCount + ExternalErrors, + Name => Name, + NumDisabledErrors => NumDisabledErrors + ) ; + else + PrintTopAlerts ( + NumErrors => NumErrors, + AlertCount => AlertLogPtr(AlertLogID).AlertCount + ExternalErrors, + Name => AlertLogPtr(AlertLogID).Name.all, + NumDisabledErrors => NumDisabledErrors + ) ; + end if ; + --Print Hierarchy when enabled and error or disabled error + if (FoundReportHierVar and ReportHierarchyVar) and (NumErrors /= 0 or NumDisabledErrors /=0) then + PrintChild( + AlertLogID => AlertLogID, + Prefix => ReportPrefix & " ", + IndentAmount => 2, + ReportAll => ReportAll + ) ; + end if ; + end procedure ReportAlerts ; + + ------------------------------------------------------------ + procedure ReportAlerts ( Name : string ; AlertCount : AlertCountType ) is + ------------------------------------------------------------ + begin + PrintTopAlerts ( + NumErrors => SumAlertCount(AlertCount), + AlertCount => AlertCount, + Name => Name, + NumDisabledErrors => 0 + ) ; + end procedure ReportAlerts ; + + ------------------------------------------------------------ + procedure ClearAlerts is + ------------------------------------------------------------ + begin + AffirmCheckCountVar := 0 ; +--?? AffirmPassedCountVar := 0 ; + + AlertLogPtr(ALERTLOG_BASE_ID).AlertCount := (0, 0, 0) ; + AlertLogPtr(ALERTLOG_BASE_ID).AlertStopCount := (FAILURE => 0, ERROR => integer'right, WARNING => integer'right) ; + + for i in ALERTLOG_BASE_ID + 1 to NumAlertLogIDsVar loop + AlertLogPtr(i).AlertCount := (0, 0, 0) ; + AlertLogPtr(i).AlertStopCount := (FAILURE => integer'right, ERROR => integer'right, WARNING => integer'right) ; + end loop ; + end procedure ClearAlerts ; + + ------------------------------------------------------------ + -- PT Local + procedure LocalLog ( + ------------------------------------------------------------ + AlertLogID : AlertLogIDType ; + Message : string ; + Level : LogType + ) is + variable buf : line ; + constant LogPrefix : string := LogPrefixVar.Get(OSVVM_DEFAULT_LOG_PREFIX) ; + begin + write(buf, LogPrefix) ; + if WriteLogLevelVar then + write(buf, " " & LOG_NAME(Level) ) ; + end if ; +--xx if (NumAlertLogIDsVar > NumPredefinedAlIDsVar) and WriteLogNameVar then -- print hierarchy names even when silent + if FoundAlertHierVar and WriteLogNameVar then +-- write(buf, " in " & justify(AlertLogPtr(AlertLogID).Name.all & ",", LEFT, AlertLogJustifyAmountVar) ) ; + write(buf, " in " & LeftJustify(AlertLogPtr(AlertLogID).Name.all & ",", AlertLogJustifyAmountVar) ) ; + end if ; + write(buf, " " & Message) ; + if WriteLogTimeVar then + write(buf, " at " & to_string(NOW, 1 ns)) ; + end if ; + writeline(buf) ; + end procedure LocalLog ; + + ------------------------------------------------------------ + procedure log ( + ------------------------------------------------------------ + AlertLogID : AlertLogIDType ; + Message : string ; + Level : LogType := ALWAYS ; + Enable : boolean := FALSE -- override internal enable + ) is + begin + if Level = ALWAYS or Enable then + LocalLog(AlertLogID, Message, Level) ; + elsif AlertLogPtr(AlertLogID).LogEnabled(Level) then + LocalLog(AlertLogID, Message, Level) ; + end if ; + end procedure log ; + + ------------------------------------------------------------ + ------------------------------------------------------------ + -- AlertLog Structure Creation and Interaction Methods + + ------------------------------------------------------------ + procedure SetAlertLogName(Name : string ) is + ------------------------------------------------------------ + begin + Deallocate(AlertLogPtr(ALERTLOG_BASE_ID).Name) ; + AlertLogPtr(ALERTLOG_BASE_ID).Name := new string'(Name) ; + end procedure SetAlertLogName ; + + ------------------------------------------------------------ + impure function GetAlertLogName(AlertLogID : AlertLogIDType) return string is + ------------------------------------------------------------ + begin + return AlertLogPtr(AlertLogID).Name.all ; + end function GetAlertLogName ; + + ------------------------------------------------------------ + -- PT Local + procedure NewAlertLogRec(AlertLogID : AlertLogIDType ; Name : string ; ParentID : AlertLogIDType) is + ------------------------------------------------------------ + variable AlertEnabled : AlertEnableType ; + variable AlertStopCount : AlertCountType ; + variable LogEnabled : LogEnableType ; + begin + if AlertLogID = ALERTLOG_BASE_ID then + AlertEnabled := (TRUE, TRUE, TRUE) ; + LogEnabled := (others => FALSE) ; + AlertStopCount := (FAILURE => 0, ERROR => integer'right, WARNING => integer'right) ; + else + if ParentID < ALERTLOG_BASE_ID then + AlertEnabled := AlertLogPtr(ALERTLOG_BASE_ID).AlertEnabled ; + LogEnabled := AlertLogPtr(ALERTLOG_BASE_ID).LogEnabled ; + else + AlertEnabled := AlertLogPtr(ParentID).AlertEnabled ; + LogEnabled := AlertLogPtr(ParentID).LogEnabled ; + end if ; + AlertStopCount := (FAILURE => integer'right, ERROR => integer'right, WARNING => integer'right) ; + end if ; + AlertLogPtr(AlertLogID) := new AlertLogRecType ; + AlertLogPtr(AlertLogID).Name := new string'(NAME) ; + AlertLogPtr(AlertLogID).ParentID := ParentID ; + AlertLogPtr(AlertLogID).AlertCount := (0, 0, 0) ; + AlertLogPtr(AlertLogID).AlertEnabled := AlertEnabled ; + AlertLogPtr(AlertLogID).AlertStopCount := AlertStopCount ; + AlertLogPtr(AlertLogID).LogEnabled := LogEnabled ; +-- AlertLogPtr(AlertLogID) := new AlertLogRecType'( +-- Name => new string'(NAME), +-- ParentID => ParentID, +-- AlertCount => (0, 0, 0), +-- AlertEnabled => AlertEnabled, +-- AlertStopCount => AlertStopCount, +-- LogEnabled => LogEnabled +-- ) ; + end procedure NewAlertLogRec ; + + ------------------------------------------------------------ + -- PT Local + -- Construct initial data structure + procedure LocalInitialize(NewNumAlertLogIDs : integer := MIN_NUM_AL_IDS) is + ------------------------------------------------------------ + begin + if NumAllocatedAlertLogIDsVar /= 0 then + Alert(ALERT_DEFAULT_ID, "AlertLogPkg: Initialize, data structure already initialized", FAILURE) ; + return ; + end if ; + -- Initialize Pointer + AlertLogPtr := new AlertLogArrayType(ALERTLOG_BASE_ID to ALERTLOG_BASE_ID + NewNumAlertLogIDs) ; + NumAllocatedAlertLogIDsVar := NewNumAlertLogIDs ; + -- Create BASE AlertLogID (if it differs from DEFAULT + if ALERTLOG_BASE_ID /= ALERT_DEFAULT_ID then + NewAlertLogRec(ALERTLOG_BASE_ID, "AlertLogTop", ALERTLOG_BASE_ID) ; + end if ; + -- Create DEFAULT AlertLogID + NewAlertLogRec(ALERT_DEFAULT_ID, "Default", ALERTLOG_BASE_ID) ; + NumAlertLogIDsVar := ALERT_DEFAULT_ID ; + -- Create OSVVM AlertLogID (if it differs from DEFAULT + if OSVVM_ALERTLOG_ID /= ALERT_DEFAULT_ID then + NewAlertLogRec(OSVVM_ALERTLOG_ID, "OSVVM", ALERTLOG_BASE_ID) ; + NumAlertLogIDsVar := NumAlertLogIDsVar + 1 ; + end if ; + if OSVVM_SCOREBOARD_ALERTLOG_ID /= OSVVM_ALERTLOG_ID then + NewAlertLogRec(OSVVM_SCOREBOARD_ALERTLOG_ID, "OSVVM Scoreboard", ALERTLOG_BASE_ID) ; + NumAlertLogIDsVar := NumAlertLogIDsVar + 1 ; + end if ; + end procedure LocalInitialize ; + + ------------------------------------------------------------ + -- Construct initial data structure + procedure Initialize(NewNumAlertLogIDs : integer := MIN_NUM_AL_IDS) is + ------------------------------------------------------------ + begin + LocalInitialize(NewNumAlertLogIDs) ; + end procedure Initialize ; + + ------------------------------------------------------------ + -- PT Local + -- Constructs initial data structure using constant below + impure function LocalInitialize return boolean is + ------------------------------------------------------------ + begin + LocalInitialize(MIN_NUM_AL_IDS) ; + return TRUE ; + end function LocalInitialize ; + + constant CONSTRUCT_ALERT_DATA_STRUCTURE : boolean := LocalInitialize ; + + ------------------------------------------------------------ + procedure Deallocate is + ------------------------------------------------------------ + begin + for i in ALERTLOG_BASE_ID to NumAlertLogIDsVar loop + Deallocate(AlertLogPtr(i).Name) ; + Deallocate(AlertLogPtr(i)) ; + end loop ; + deallocate(AlertLogPtr) ; + -- Free up space used by protected types within AlertLogPkg + AlertPrefixVar.Deallocate ; + LogPrefixVar.Deallocate ; + ReportPrefixVar.Deallocate ; + DoneNameVar.Deallocate ; + PassNameVar.Deallocate ; + FailNameVar.Deallocate ; + -- Restore variables to their initial state + NumAlertLogIDsVar := 0 ; + NumAllocatedAlertLogIDsVar := 0 ; + GlobalAlertEnabledVar := TRUE ; -- Allows turn off and on + AffirmCheckCountVar := 0 ; +--?? AffirmPassedCountVar := 0 ; + FailOnWarningVar := TRUE ; + FailOnDisabledErrorsVar := TRUE ; + ReportHierarchyVar := TRUE ; + FoundReportHierVar := FALSE ; + FoundAlertHierVar := FALSE ; + WriteAlertLevelVar := TRUE ; + WriteAlertNameVar := TRUE ; + WriteAlertTimeVar := TRUE ; + WriteLogLevelVar := TRUE ; + WriteLogNameVar := TRUE ; + WriteLogTimeVar := TRUE ; + end procedure Deallocate ; + + ------------------------------------------------------------ + -- PT Local. + procedure GrowAlertStructure (NewNumAlertLogIDs : integer) is + ------------------------------------------------------------ + variable oldAlertLogPtr : AlertLogArrayPtrType ; + begin + if NumAllocatedAlertLogIDsVar = 0 then + Initialize (NewNumAlertLogIDs) ; -- Construct initial structure + else + oldAlertLogPtr := AlertLogPtr ; + AlertLogPtr := new AlertLogArrayType(ALERTLOG_BASE_ID to NewNumAlertLogIDs) ; + AlertLogPtr(ALERTLOG_BASE_ID to NumAlertLogIDsVar) := oldAlertLogPtr(ALERTLOG_BASE_ID to NumAlertLogIDsVar) ; + deallocate(oldAlertLogPtr) ; + end if ; + NumAllocatedAlertLogIDsVar := NewNumAlertLogIDs ; + end procedure GrowAlertStructure ; + + ------------------------------------------------------------ + -- Sets a AlertLogPtr to a particular size + -- Use for small bins to save space or large bins to + -- suppress the resize and copy as a CovBin autosizes. + procedure SetNumAlertLogIDs (NewNumAlertLogIDs : integer) is + ------------------------------------------------------------ + variable oldAlertLogPtr : AlertLogArrayPtrType ; + begin + if NewNumAlertLogIDs > NumAllocatedAlertLogIDsVar then + GrowAlertStructure(NewNumAlertLogIDs) ; + end if; + end procedure SetNumAlertLogIDs ; + + ------------------------------------------------------------ + -- PT Local + impure function GetNextAlertLogID return AlertLogIDType is + ------------------------------------------------------------ + variable NewNumAlertLogIDs : AlertLogIDType ; + begin + NewNumAlertLogIDs := NumAlertLogIDsVar + 1 ; + if NewNumAlertLogIDs > NumAllocatedAlertLogIDsVar then + GrowAlertStructure(NumAllocatedAlertLogIDsVar + MIN_NUM_AL_IDS) ; + end if ; + NumAlertLogIDsVar := NewNumAlertLogIDs ; + return NumAlertLogIDsVar ; + end function GetNextAlertLogID ; + + ------------------------------------------------------------ + impure function FindAlertLogID(Name : string ) return AlertLogIDType is + ------------------------------------------------------------ + begin + for i in ALERTLOG_BASE_ID to NumAlertLogIDsVar loop + if Name = AlertLogPtr(i).Name.all then + return i ; + end if ; + end loop ; + return ALERTLOG_ID_NOT_FOUND ; -- not found + end function FindAlertLogID ; + + ------------------------------------------------------------ + impure function FindAlertLogID(Name : string ; ParentID : AlertLogIDType) return AlertLogIDType is + ------------------------------------------------------------ + variable CurParentID : AlertLogIDType ; + begin + for i in ALERTLOG_BASE_ID to NumAlertLogIDsVar loop + CurParentID := AlertLogPtr(i).ParentID ; + if Name = AlertLogPtr(i).Name.all and + (CurParentID = ParentID or CurParentID = ALERTLOG_ID_NOT_ASSIGNED or ParentID = ALERTLOG_ID_NOT_ASSIGNED) + then + return i ; + end if ; + end loop ; + return ALERTLOG_ID_NOT_FOUND ; -- not found + end function FindAlertLogID ; + + ------------------------------------------------------------ + impure function GetAlertLogID(Name : string ; ParentID : AlertLogIDType ; CreateHierarchy : Boolean) return AlertLogIDType is + ------------------------------------------------------------ + variable ResultID : AlertLogIDType ; + begin + ResultID := FindAlertLogID(Name, ParentID) ; + if ResultID /= ALERTLOG_ID_NOT_FOUND then + -- found it, set ParentID + if AlertLogPtr(ResultID).ParentID = ALERTLOG_ID_NOT_ASSIGNED then + AlertLogPtr(ResultID).ParentID := ParentID ; + -- else -- do not update as ParentIDs are either same or input ParentID = ALERTLOG_ID_NOT_ASSIGNED + end if ; + else + ResultID := GetNextAlertLogID ; + NewAlertLogRec(ResultID, Name, ParentID) ; + FoundAlertHierVar := TRUE ; + if CreateHierarchy then + FoundReportHierVar := TRUE ; + end if ; + end if ; + return ResultID ; + end function GetAlertLogID ; + + ------------------------------------------------------------ + impure function GetAlertLogParentID(AlertLogID : AlertLogIDType) return AlertLogIDType is + ------------------------------------------------------------ + begin + return AlertLogPtr(AlertLogID).ParentID ; + end function GetAlertLogParentID ; + + ------------------------------------------------------------ + ------------------------------------------------------------ + -- Accessor Methods + ------------------------------------------------------------ + + ------------------------------------------------------------ + procedure SetGlobalAlertEnable (A : boolean := TRUE) is + ------------------------------------------------------------ + begin + GlobalAlertEnabledVar := A ; + end procedure SetGlobalAlertEnable ; + + ------------------------------------------------------------ + impure function GetGlobalAlertEnable return boolean is + ------------------------------------------------------------ + begin + return GlobalAlertEnabledVar ; + end function GetGlobalAlertEnable ; + + ------------------------------------------------------------ + procedure IncAffirmCount is + ------------------------------------------------------------ + begin + if GlobalAlertEnabledVar then + AffirmCheckCountVar := AffirmCheckCountVar + 1 ; + end if ; + end procedure IncAffirmCount ; + + ------------------------------------------------------------ + impure function GetAffirmCount return natural is + ------------------------------------------------------------ + begin + return AffirmCheckCountVar ; + end function GetAffirmCount ; + +--?? ------------------------------------------------------------ +--?? procedure IncAffirmPassCount is +--?? ------------------------------------------------------------ +--?? begin +--?? if GlobalAlertEnabledVar then +--?? AffirmCheckCountVar := AffirmCheckCountVar + 1 ; +--?? AffirmPassedCountVar := AffirmPassedCountVar + 1 ; +--?? end if ; +--?? end procedure IncAffirmPassCount ; +--?? +--?? ------------------------------------------------------------ +--?? impure function GetAffirmPassCount return natural is +--?? ------------------------------------------------------------ +--?? begin +--?? return AffirmPassedCountVar ; +--?? end function GetAffirmPassCount ; + + ------------------------------------------------------------ + -- PT LOCAL + procedure SetOneStopCount( + ------------------------------------------------------------ + AlertLogID : AlertLogIDType ; + Level : AlertType ; + Count : integer + ) is + begin + if AlertLogPtr(AlertLogID).AlertStopCount(Level) = integer'right then + AlertLogPtr(AlertLogID).AlertStopCount(Level) := Count ; + else + AlertLogPtr(AlertLogID).AlertStopCount(Level) := + AlertLogPtr(AlertLogID).AlertStopCount(Level) + Count ; + end if ; + end procedure SetOneStopCount ; + + ------------------------------------------------------------ + procedure SetAlertStopCount(AlertLogID : AlertLogIDType ; Level : AlertType ; Count : integer) is + ------------------------------------------------------------ + begin + SetOneStopCount(AlertLogID, Level, Count) ; + if AlertLogID /= ALERTLOG_BASE_ID then + SetAlertStopCount(AlertLogPtr(AlertLogID).ParentID, Level, Count) ; + end if ; + end procedure SetAlertStopCount ; + + ------------------------------------------------------------ + impure function GetAlertStopCount(AlertLogID : AlertLogIDType ; Level : AlertType) return integer is + ------------------------------------------------------------ + begin + return AlertLogPtr(AlertLogID).AlertStopCount(Level) ; + end function GetAlertStopCount ; + + ------------------------------------------------------------ + procedure SetAlertEnable(Level : AlertType ; Enable : boolean) is + ------------------------------------------------------------ + begin + for i in ALERTLOG_BASE_ID to NumAlertLogIDsVar loop + AlertLogPtr(i).AlertEnabled(Level) := Enable ; + end loop ; + end procedure SetAlertEnable ; + + ------------------------------------------------------------ + procedure SetAlertEnable(AlertLogID : AlertLogIDType ; Level : AlertType ; Enable : boolean ; DescendHierarchy : boolean := TRUE) is + ------------------------------------------------------------ + begin + AlertLogPtr(AlertLogID).AlertEnabled(Level) := Enable ; + if DescendHierarchy then + for i in AlertLogID+1 to NumAlertLogIDsVar loop + if AlertLogID = AlertLogPtr(i).ParentID then + SetAlertEnable(i, Level, Enable, DescendHierarchy) ; + end if ; + end loop ; + end if ; + end procedure SetAlertEnable ; + + ------------------------------------------------------------ + impure function GetAlertEnable(AlertLogID : AlertLogIDType ; Level : AlertType) return boolean is + ------------------------------------------------------------ + begin + return AlertLogPtr(AlertLogID).AlertEnabled(Level) ; + end function GetAlertEnable ; + + ------------------------------------------------------------ + procedure SetLogEnable(Level : LogType ; Enable : boolean) is + ------------------------------------------------------------ + begin + for i in ALERTLOG_BASE_ID to NumAlertLogIDsVar loop + AlertLogPtr(i).LogEnabled(Level) := Enable ; + end loop ; + end procedure SetLogEnable ; + + ------------------------------------------------------------ + procedure SetLogEnable(AlertLogID : AlertLogIDType ; Level : LogType ; Enable : boolean ; DescendHierarchy : boolean := TRUE) is + ------------------------------------------------------------ + begin + AlertLogPtr(AlertLogID).LogEnabled(Level) := Enable ; + if DescendHierarchy then + for i in AlertLogID+1 to NumAlertLogIDsVar loop + if AlertLogID = AlertLogPtr(i).ParentID then + SetLogEnable(i, Level, Enable, DescendHierarchy) ; + end if ; + end loop ; + end if ; + end procedure SetLogEnable ; + + ------------------------------------------------------------ + impure function GetLogEnable(AlertLogID : AlertLogIDType ; Level : LogType) return boolean is + ------------------------------------------------------------ + begin + if Level = ALWAYS then + return TRUE ; + else + return AlertLogPtr(AlertLogID).LogEnabled(Level) ; + end if ; + end function GetLogEnable ; + + ------------------------------------------------------------ + -- PT Local + procedure PrintLogLevels( + ------------------------------------------------------------ + AlertLogID : AlertLogIDType ; + Prefix : string ; + IndentAmount : integer + ) is + variable buf : line ; + begin + write(buf, Prefix & " " & LeftJustify(AlertLogPtr(AlertLogID).Name.all, ReportJustifyAmountVar - IndentAmount)) ; + for i in LogIndexType loop + if AlertLogPtr(AlertLogID).LogEnabled(i) then +-- write(buf, " " & to_string(AlertLogPtr(AlertLogID).LogEnabled(i)) ) ; + write(buf, " " & to_string(i)) ; + end if ; + end loop ; + WriteLine(buf) ; + for i in AlertLogID+1 to NumAlertLogIDsVar loop + if AlertLogID = AlertLogPtr(i).ParentID then + PrintLogLevels( + AlertLogID => i, + Prefix => Prefix & " ", + IndentAmount => IndentAmount + 2 + ) ; + end if ; + end loop ; + end procedure PrintLogLevels ; + + ------------------------------------------------------------ + procedure ReportLogEnables is + ------------------------------------------------------------ + begin + if ReportJustifyAmountVar <= 0 then + SetJustify ; + end if ; + PrintLogLevels(ALERTLOG_BASE_ID, "", 0) ; + end procedure ReportLogEnables ; + + ------------------------------------------------------------ + procedure SetAlertLogOptions ( + ------------------------------------------------------------ + FailOnWarning : AlertLogOptionsType := OPT_INIT_PARM_DETECT ; + FailOnDisabledErrors : AlertLogOptionsType := OPT_INIT_PARM_DETECT ; + ReportHierarchy : AlertLogOptionsType := OPT_INIT_PARM_DETECT ; + WriteAlertLevel : AlertLogOptionsType := OPT_INIT_PARM_DETECT ; + WriteAlertName : AlertLogOptionsType := OPT_INIT_PARM_DETECT ; + WriteAlertTime : AlertLogOptionsType := OPT_INIT_PARM_DETECT ; + WriteLogLevel : AlertLogOptionsType := OPT_INIT_PARM_DETECT ; + WriteLogName : AlertLogOptionsType := OPT_INIT_PARM_DETECT ; + WriteLogTime : AlertLogOptionsType := OPT_INIT_PARM_DETECT ; + AlertPrefix : string := OSVVM_STRING_INIT_PARM_DETECT ; + LogPrefix : string := OSVVM_STRING_INIT_PARM_DETECT ; + ReportPrefix : string := OSVVM_STRING_INIT_PARM_DETECT ; + DoneName : string := OSVVM_STRING_INIT_PARM_DETECT ; + PassName : string := OSVVM_STRING_INIT_PARM_DETECT ; + FailName : string := OSVVM_STRING_INIT_PARM_DETECT + ) is + begin + if FailOnWarning /= OPT_INIT_PARM_DETECT then + FailOnWarningVar := IsEnabled(FailOnWarning) ; + end if ; + if FailOnDisabledErrors /= OPT_INIT_PARM_DETECT then + FailOnDisabledErrorsVar := IsEnabled(FailOnDisabledErrors) ; + end if ; + if ReportHierarchy /= OPT_INIT_PARM_DETECT then + ReportHierarchyVar := IsEnabled(ReportHierarchy) ; + end if ; + if WriteAlertLevel /= OPT_INIT_PARM_DETECT then + WriteAlertLevelVar := IsEnabled(WriteAlertLevel) ; + end if ; + if WriteAlertName /= OPT_INIT_PARM_DETECT then + WriteAlertNameVar := IsEnabled(WriteAlertName) ; + end if ; + if WriteAlertTime /= OPT_INIT_PARM_DETECT then + WriteAlertTimeVar := IsEnabled(WriteAlertTime) ; + end if ; + if WriteLogLevel /= OPT_INIT_PARM_DETECT then + WriteLogLevelVar := IsEnabled(WriteLogLevel) ; + end if ; + if WriteLogName /= OPT_INIT_PARM_DETECT then + WriteLogNameVar := IsEnabled(WriteLogName) ; + end if ; + if WriteLogTime /= OPT_INIT_PARM_DETECT then + WriteLogTimeVar := IsEnabled(WriteLogTime) ; + end if ; + if AlertPrefix /= OSVVM_STRING_INIT_PARM_DETECT then + AlertPrefixVar.Set(AlertPrefix) ; + end if ; + if LogPrefix /= OSVVM_STRING_INIT_PARM_DETECT then + LogPrefixVar.Set(LogPrefix) ; + end if ; + if ReportPrefix /= OSVVM_STRING_INIT_PARM_DETECT then + ReportPrefixVar.Set(ReportPrefix) ; + end if ; + if DoneName /= OSVVM_STRING_INIT_PARM_DETECT then + DoneNameVar.Set(DoneName) ; + end if ; + if PassName /= OSVVM_STRING_INIT_PARM_DETECT then + PassNameVar.Set(PassName) ; + end if ; + if FailName /= OSVVM_STRING_INIT_PARM_DETECT then + FailNameVar.Set(FailName) ; + end if ; + end procedure SetAlertLogOptions ; + + ------------------------------------------------------------ + procedure ReportAlertLogOptions is + ------------------------------------------------------------ + variable buf : line ; + begin + -- Boolean Values + swrite(buf, "ReportAlertLogOptions" & LF ) ; + swrite(buf, "---------------------" & LF ) ; + swrite(buf, "FailOnWarningVar: " & to_string(FailOnWarningVar ) & LF ) ; + swrite(buf, "FailOnDisabledErrorsVar: " & to_string(FailOnDisabledErrorsVar ) & LF ) ; + swrite(buf, "ReportHierarchyVar: " & to_string(ReportHierarchyVar ) & LF ) ; + swrite(buf, "FoundReportHierVar: " & to_string(FoundReportHierVar ) & LF ) ; -- Not set by user + swrite(buf, "FoundAlertHierVar: " & to_string(FoundAlertHierVar ) & LF ) ; -- Not set by user + swrite(buf, "WriteAlertLevelVar: " & to_string(WriteAlertLevelVar ) & LF ) ; + swrite(buf, "WriteAlertNameVar: " & to_string(WriteAlertNameVar ) & LF ) ; + swrite(buf, "WriteAlertTimeVar: " & to_string(WriteAlertTimeVar ) & LF ) ; + swrite(buf, "WriteLogLevelVar: " & to_string(WriteLogLevelVar ) & LF ) ; + swrite(buf, "WriteLogNameVar: " & to_string(WriteLogNameVar ) & LF ) ; + swrite(buf, "WriteLogTimeVar: " & to_string(WriteLogTimeVar ) & LF ) ; + + -- String + swrite(buf, "AlertPrefixVar: " & string'(AlertPrefixVar.Get(OSVVM_DEFAULT_ALERT_PREFIX)) & LF ) ; + swrite(buf, "LogPrefixVar: " & string'(LogPrefixVar.Get(OSVVM_DEFAULT_LOG_PREFIX)) & LF ) ; + swrite(buf, "ReportPrefixVar: " & ResolveOsvvmWritePrefix(ReportPrefixVar.GetOpt) & LF ) ; + swrite(buf, "DoneNameVar: " & ResolveOsvvmDoneName(DoneNameVar.GetOpt) & LF ) ; + swrite(buf, "PassNameVar: " & ResolveOsvvmPassName(PassNameVar.GetOpt) & LF ) ; + swrite(buf, "FailNameVar: " & ResolveOsvvmFailName(FailNameVar.GetOpt) & LF ) ; + writeline(buf) ; + end procedure ReportAlertLogOptions ; + + ------------------------------------------------------------ + impure function GetAlertLogFailOnWarning return AlertLogOptionsType is + ------------------------------------------------------------ + begin + return to_OsvvmOptionsType(FailOnWarningVar) ; + end function GetAlertLogFailOnWarning ; + + ------------------------------------------------------------ + impure function GetAlertLogFailOnDisabledErrors return AlertLogOptionsType is + ------------------------------------------------------------ + begin + return to_OsvvmOptionsType(FailOnDisabledErrorsVar) ; + end function GetAlertLogFailOnDisabledErrors ; + + ------------------------------------------------------------ + impure function GetAlertLogReportHierarchy return AlertLogOptionsType is + ------------------------------------------------------------ + begin + return to_OsvvmOptionsType(ReportHierarchyVar) ; + end function GetAlertLogReportHierarchy ; + + ------------------------------------------------------------ + impure function GetAlertLogFoundReportHier return boolean is + ------------------------------------------------------------ + begin + return FoundReportHierVar ; + end function GetAlertLogFoundReportHier ; + + ------------------------------------------------------------ + impure function GetAlertLogFoundAlertHier return boolean is + ------------------------------------------------------------ + begin + return FoundAlertHierVar ; + end function GetAlertLogFoundAlertHier ; + + ------------------------------------------------------------ + impure function GetAlertLogWriteAlertLevel return AlertLogOptionsType is + ------------------------------------------------------------ + begin + return to_OsvvmOptionsType(WriteAlertLevelVar) ; + end function GetAlertLogWriteAlertLevel ; + + ------------------------------------------------------------ + impure function GetAlertLogWriteAlertName return AlertLogOptionsType is + ------------------------------------------------------------ + begin + return to_OsvvmOptionsType(WriteAlertNameVar) ; + end function GetAlertLogWriteAlertName ; + + ------------------------------------------------------------ + impure function GetAlertLogWriteAlertTime return AlertLogOptionsType is + ------------------------------------------------------------ + begin + return to_OsvvmOptionsType(WriteAlertTimeVar) ; + end function GetAlertLogWriteAlertTime ; + + ------------------------------------------------------------ + impure function GetAlertLogWriteLogLevel return AlertLogOptionsType is + ------------------------------------------------------------ + begin + return to_OsvvmOptionsType(WriteLogLevelVar) ; + end function GetAlertLogWriteLogLevel ; + + ------------------------------------------------------------ + impure function GetAlertLogWriteLogName return AlertLogOptionsType is + ------------------------------------------------------------ + begin + return to_OsvvmOptionsType(WriteLogNameVar) ; + end function GetAlertLogWriteLogName ; + + ------------------------------------------------------------ + impure function GetAlertLogWriteLogTime return AlertLogOptionsType is + ------------------------------------------------------------ + begin + return to_OsvvmOptionsType(WriteLogTimeVar) ; + end function GetAlertLogWriteLogTime ; + + ------------------------------------------------------------ + impure function GetAlertLogAlertPrefix return string is + ------------------------------------------------------------ + begin + return AlertPrefixVar.Get(OSVVM_DEFAULT_ALERT_PREFIX) ; + end function GetAlertLogAlertPrefix ; + + ------------------------------------------------------------ + impure function GetAlertLogLogPrefix return string is + ------------------------------------------------------------ + begin + return LogPrefixVar.Get(OSVVM_DEFAULT_LOG_PREFIX) ; + end function GetAlertLogLogPrefix ; + + ------------------------------------------------------------ + impure function GetAlertLogReportPrefix return string is + ------------------------------------------------------------ + begin + return ResolveOsvvmWritePrefix(ReportPrefixVar.GetOpt) ; + end function GetAlertLogReportPrefix ; + + ------------------------------------------------------------ + impure function GetAlertLogDoneName return string is + ------------------------------------------------------------ + begin + return ResolveOsvvmDoneName(DoneNameVar.GetOpt) ; + end function GetAlertLogDoneName ; + + ------------------------------------------------------------ + impure function GetAlertLogPassName return string is + ------------------------------------------------------------ + begin + return ResolveOsvvmPassName(PassNameVar.GetOpt) ; + end function GetAlertLogPassName ; + + ------------------------------------------------------------ + impure function GetAlertLogFailName return string is + ------------------------------------------------------------ + begin + return ResolveOsvvmFailName(FailNameVar.GetOpt) ; + end function GetAlertLogFailName ; + + end protected body AlertLogStructPType ; + + + + shared variable AlertLogStruct : AlertLogStructPType ; + +--- /////////////////////////////////////////////////////////////////////////// +--- /////////////////////////////////////////////////////////////////////////// +--- /////////////////////////////////////////////////////////////////////////// + + ------------------------------------------------------------ + procedure Alert( + ------------------------------------------------------------ + AlertLogID : AlertLogIDType ; + Message : string ; + Level : AlertType := ERROR + ) is + begin + AlertLogStruct.Alert(AlertLogID, Message, Level) ; + end procedure alert ; + + ------------------------------------------------------------ + procedure Alert( Message : string ; Level : AlertType := ERROR ) is + ------------------------------------------------------------ + begin + AlertLogStruct.Alert(ALERT_DEFAULT_ID, Message, Level) ; + end procedure alert ; + + ------------------------------------------------------------ + procedure IncAlertCount( + ------------------------------------------------------------ + AlertLogID : AlertLogIDType ; + Level : AlertType := ERROR + ) is + begin + AlertLogStruct.IncAlertCount(AlertLogID, Level) ; + end procedure IncAlertCount ; + + ------------------------------------------------------------ + procedure IncAlertCount( Level : AlertType := ERROR ) is + ------------------------------------------------------------ + begin + AlertLogStruct.IncAlertCount(ALERT_DEFAULT_ID, Level) ; + end procedure IncAlertCount ; + + + ------------------------------------------------------------ + procedure AlertIf( AlertLogID : AlertLogIDType ; condition : boolean ; Message : string ; Level : AlertType := ERROR ) is + ------------------------------------------------------------ + begin + if condition then + AlertLogStruct.Alert(AlertLogID , Message, Level) ; + end if ; + end procedure AlertIf ; + + ------------------------------------------------------------ + procedure AlertIf( condition : boolean ; Message : string ; Level : AlertType := ERROR ) is + ------------------------------------------------------------ + begin + if condition then + AlertLogStruct.Alert(ALERT_DEFAULT_ID , Message, Level) ; + end if ; + end procedure AlertIf ; + + ------------------------------------------------------------ + -- useful in a loop: exit when AlertIf( not ReadValid, failure, "Read Failed") ; + impure function AlertIf( AlertLogID : AlertLogIDType ; condition : boolean ; Message : string ; Level : AlertType := ERROR ) return boolean is + ------------------------------------------------------------ + begin + if condition then + AlertLogStruct.Alert(AlertLogID , Message, Level) ; + end if ; + return condition ; + end function AlertIf ; + + ------------------------------------------------------------ + impure function AlertIf( condition : boolean ; Message : string ; Level : AlertType := ERROR ) return boolean is + ------------------------------------------------------------ + begin + if condition then + AlertLogStruct.Alert(ALERT_DEFAULT_ID, Message, Level) ; + end if ; + return condition ; + end function AlertIf ; + + ------------------------------------------------------------ + procedure AlertIfNot( AlertLogID : AlertLogIDType ; condition : boolean ; Message : string ; Level : AlertType := ERROR ) is + ------------------------------------------------------------ + begin + if not condition then + AlertLogStruct.Alert(AlertLogID, Message, Level) ; + end if ; + end procedure AlertIfNot ; + + ------------------------------------------------------------ + procedure AlertIfNot( condition : boolean ; Message : string ; Level : AlertType := ERROR ) is + ------------------------------------------------------------ + begin + if not condition then + AlertLogStruct.Alert(ALERT_DEFAULT_ID, Message, Level) ; + end if ; + end procedure AlertIfNot ; + + ------------------------------------------------------------ + -- useful in a loop: exit when AlertIfNot( not ReadValid, failure, "Read Failed") ; + impure function AlertIfNot( AlertLogID : AlertLogIDType ; condition : boolean ; Message : string ; Level : AlertType := ERROR ) return boolean is + ------------------------------------------------------------ + begin + if not condition then + AlertLogStruct.Alert(AlertLogID, Message, Level) ; + end if ; + return not condition ; + end function AlertIfNot ; + + ------------------------------------------------------------ + impure function AlertIfNot( condition : boolean ; Message : string ; Level : AlertType := ERROR ) return boolean is + ------------------------------------------------------------ + begin + if not condition then + AlertLogStruct.Alert(ALERT_DEFAULT_ID, Message, Level) ; + end if ; + return not condition ; + end function AlertIfNot ; + + + ------------------------------------------------------------ + -- AlertIfEqual with AlertLogID + ------------------------------------------------------------ + procedure AlertIfEqual( AlertLogID : AlertLogIDType ; L, R : std_logic ; Message : string ; Level : AlertType := ERROR ) is + ------------------------------------------------------------ + begin + if L ?= R then + AlertLogStruct.Alert(AlertLogID, Message & " L = R, L = " & to_string(L) & " R = " & to_string(R), Level) ; + end if ; + end procedure AlertIfEqual ; + + ------------------------------------------------------------ + procedure AlertIfEqual( AlertLogID : AlertLogIDType ; L, R : std_logic_vector ; Message : string ; Level : AlertType := ERROR ) is + ------------------------------------------------------------ + begin + if L ?= R then + AlertLogStruct.Alert(AlertLogID, Message & " L = R, L = " & to_string(L) & " R = " & to_string(R), Level) ; + end if ; + end procedure AlertIfEqual ; + + ------------------------------------------------------------ + procedure AlertIfEqual( AlertLogID : AlertLogIDType ; L, R : unsigned ; Message : string ; Level : AlertType := ERROR ) is + ------------------------------------------------------------ + begin + if L ?= R then + AlertLogStruct.Alert(AlertLogID, Message & " L = R, L = " & to_string(L) & " R = " & to_string(R), Level) ; + end if ; + end procedure AlertIfEqual ; + + ------------------------------------------------------------ + procedure AlertIfEqual( AlertLogID : AlertLogIDType ; L, R : signed ; Message : string ; Level : AlertType := ERROR ) is + ------------------------------------------------------------ + begin + if L ?= R then + AlertLogStruct.Alert(AlertLogID, Message & " L = R, L = " & to_string(L) & " R = " & to_string(R), Level) ; + end if ; + end procedure AlertIfEqual ; + + ------------------------------------------------------------ + procedure AlertIfEqual( AlertLogID : AlertLogIDType ; L, R : integer ; Message : string ; Level : AlertType := ERROR ) is + ------------------------------------------------------------ + begin + if L = R then + AlertLogStruct.Alert(AlertLogID, Message & " L = R, L = " & to_string(L) & " R = " & to_string(R), Level) ; + end if ; + end procedure AlertIfEqual ; + + ------------------------------------------------------------ + procedure AlertIfEqual( AlertLogID : AlertLogIDType ; L, R : real ; Message : string ; Level : AlertType := ERROR ) is + ------------------------------------------------------------ + begin + if L = R then + AlertLogStruct.Alert(AlertLogID, Message & " L = R, L = " & to_string(L, 4) & " R = " & to_string(R, 4), Level) ; + end if ; + end procedure AlertIfEqual ; + + ------------------------------------------------------------ + procedure AlertIfEqual( AlertLogID : AlertLogIDType ; L, R : character ; Message : string ; Level : AlertType := ERROR ) is + ------------------------------------------------------------ + begin + if L = R then + AlertLogStruct.Alert(AlertLogID, Message & " L = R, L = " & L & " R = " & R, Level) ; + end if ; + end procedure AlertIfEqual ; + + ------------------------------------------------------------ + procedure AlertIfEqual( AlertLogID : AlertLogIDType ; L, R : string ; Message : string ; Level : AlertType := ERROR ) is + ------------------------------------------------------------ + begin + if L = R then + AlertLogStruct.Alert(AlertLogID, Message & " L = R, L = " & L & " R = " & R, Level) ; + end if ; + end procedure AlertIfEqual ; + + ------------------------------------------------------------ + procedure AlertIfEqual( AlertLogID : AlertLogIDType ; L, R : time ; Message : string ; Level : AlertType := ERROR ) is + ------------------------------------------------------------ + begin + if L = R then + AlertLogStruct.Alert(AlertLogID, Message & " L = R, L = " & to_string(L) & " R = " & to_string(R), Level) ; + end if ; + end procedure AlertIfEqual ; + + + ------------------------------------------------------------ + -- AlertIfEqual without AlertLogID + ------------------------------------------------------------ + procedure AlertIfEqual( L, R : std_logic ; Message : string ; Level : AlertType := ERROR ) is + ------------------------------------------------------------ + begin + if L ?= R then + AlertLogStruct.Alert(ALERT_DEFAULT_ID, Message & " L = R, L = " & to_string(L) & " R = " & to_string(R), Level) ; + end if ; + end procedure AlertIfEqual ; + + ------------------------------------------------------------ + procedure AlertIfEqual( L, R : std_logic_vector ; Message : string ; Level : AlertType := ERROR ) is + ------------------------------------------------------------ + begin + if L ?= R then + AlertLogStruct.Alert(ALERT_DEFAULT_ID, Message & " L = R, L = " & to_string(L) & " R = " & to_string(R), Level) ; + end if ; + end procedure AlertIfEqual ; + + ------------------------------------------------------------ + procedure AlertIfEqual( L, R : unsigned ; Message : string ; Level : AlertType := ERROR ) is + ------------------------------------------------------------ + begin + if L ?= R then + AlertLogStruct.Alert(ALERT_DEFAULT_ID, Message & " L = R, L = " & to_string(L) & " R = " & to_string(R), Level) ; + end if ; + end procedure AlertIfEqual ; + + ------------------------------------------------------------ + procedure AlertIfEqual( L, R : signed ; Message : string ; Level : AlertType := ERROR ) is + ------------------------------------------------------------ + begin + if L ?= R then + AlertLogStruct.Alert(ALERT_DEFAULT_ID, Message & " L = R, L = " & to_string(L) & " R = " & to_string(R), Level) ; + end if ; + end procedure AlertIfEqual ; + + ------------------------------------------------------------ + procedure AlertIfEqual( L, R : integer ; Message : string ; Level : AlertType := ERROR ) is + ------------------------------------------------------------ + begin + if L = R then + AlertLogStruct.Alert(ALERT_DEFAULT_ID, Message & " L = R, L = " & to_string(L) & " R = " & to_string(R), Level) ; + end if ; + end procedure AlertIfEqual ; + + ------------------------------------------------------------ + procedure AlertIfEqual( L, R : real ; Message : string ; Level : AlertType := ERROR ) is + ------------------------------------------------------------ + begin + if L = R then + AlertLogStruct.Alert(ALERT_DEFAULT_ID, Message & " L = R, L = " & to_string(L, 4) & " R = " & to_string(R, 4), Level) ; + end if ; + end procedure AlertIfEqual ; + + ------------------------------------------------------------ + procedure AlertIfEqual( L, R : character ; Message : string ; Level : AlertType := ERROR ) is + ------------------------------------------------------------ + begin + if L = R then + AlertLogStruct.Alert(ALERT_DEFAULT_ID, Message & " L = R, L = " & L & " R = " & R, Level) ; + end if ; + end procedure AlertIfEqual ; + + ------------------------------------------------------------ + procedure AlertIfEqual( L, R : string ; Message : string ; Level : AlertType := ERROR ) is + ------------------------------------------------------------ + begin + if L = R then + AlertLogStruct.Alert(ALERT_DEFAULT_ID, Message & " L = R, L = " & L & " R = " & R, Level) ; + end if ; + end procedure AlertIfEqual ; + + ------------------------------------------------------------ + procedure AlertIfEqual( L, R : time ; Message : string ; Level : AlertType := ERROR ) is + ------------------------------------------------------------ + begin + if L = R then + AlertLogStruct.Alert(ALERT_DEFAULT_ID, Message & " L = R, L = " & to_string(L) & " R = " & to_string(R), Level) ; + end if ; + end procedure AlertIfEqual ; + + + ------------------------------------------------------------ + -- AlertIfNotEqual with AlertLogID + ------------------------------------------------------------ + procedure AlertIfNotEqual( AlertLogID : AlertLogIDType ; L, R : std_logic ; Message : string ; Level : AlertType := ERROR ) is + ------------------------------------------------------------ + begin + if L ?/= R then + AlertLogStruct.Alert(AlertLogID, Message & " L /= R, L = " & to_string(L) & " R = " & to_string(R), Level) ; + end if ; + end procedure AlertIfNotEqual ; + + ------------------------------------------------------------ + procedure AlertIfNotEqual( AlertLogID : AlertLogIDType ; L, R : std_logic_vector ; Message : string ; Level : AlertType := ERROR ) is + ------------------------------------------------------------ + begin + if L ?/= R then + AlertLogStruct.Alert(AlertLogID, Message & " L /= R, L = " & to_string(L) & " R = " & to_string(R), Level) ; + end if ; + end procedure AlertIfNotEqual ; + + ------------------------------------------------------------ + procedure AlertIfNotEqual( AlertLogID : AlertLogIDType ; L, R : unsigned ; Message : string ; Level : AlertType := ERROR ) is + ------------------------------------------------------------ + begin + if L ?/= R then + AlertLogStruct.Alert(AlertLogID, Message & " L /= R, L = " & to_string(L) & " R = " & to_string(R), Level) ; + end if ; + end procedure AlertIfNotEqual ; + + ------------------------------------------------------------ + procedure AlertIfNotEqual( AlertLogID : AlertLogIDType ; L, R : signed ; Message : string ; Level : AlertType := ERROR ) is + ------------------------------------------------------------ + begin + if L ?/= R then + AlertLogStruct.Alert(AlertLogID, Message & " L /= R, L = " & to_string(L) & " R = " & to_string(R), Level) ; + end if ; + end procedure AlertIfNotEqual ; + + ------------------------------------------------------------ + procedure AlertIfNotEqual( AlertLogID : AlertLogIDType ; L, R : integer ; Message : string ; Level : AlertType := ERROR ) is + ------------------------------------------------------------ + begin + if L /= R then + AlertLogStruct.Alert(AlertLogID, Message & " L /= R, L = " & to_string(L) & " R = " & to_string(R), Level) ; + end if ; + end procedure AlertIfNotEqual ; + + ------------------------------------------------------------ + procedure AlertIfNotEqual( AlertLogID : AlertLogIDType ; L, R : real ; Message : string ; Level : AlertType := ERROR ) is + ------------------------------------------------------------ + begin + if L /= R then + AlertLogStruct.Alert(AlertLogID, Message & " L /= R, L = " & to_string(L, 4) & " R = " & to_string(R, 4), Level) ; + end if ; + end procedure AlertIfNotEqual ; + + ------------------------------------------------------------ + procedure AlertIfNotEqual( AlertLogID : AlertLogIDType ; L, R : character ; Message : string ; Level : AlertType := ERROR ) is + ------------------------------------------------------------ + begin + if L /= R then + AlertLogStruct.Alert(AlertLogID, Message & " L /= R, L = " & L & " R = " & R, Level) ; + end if ; + end procedure AlertIfNotEqual ; + + ------------------------------------------------------------ + procedure AlertIfNotEqual( AlertLogID : AlertLogIDType ; L, R : string ; Message : string ; Level : AlertType := ERROR ) is + ------------------------------------------------------------ + begin + if L /= R then + AlertLogStruct.Alert(AlertLogID, Message & " L /= R, L = " & L & " R = " & R, Level) ; + end if ; + end procedure AlertIfNotEqual ; + + ------------------------------------------------------------ + procedure AlertIfNotEqual( AlertLogID : AlertLogIDType ; L, R : time ; Message : string ; Level : AlertType := ERROR ) is + ------------------------------------------------------------ + begin + if L /= R then + AlertLogStruct.Alert(AlertLogID, Message & " L /= R, L = " & to_string(L) & " R = " & to_string(R), Level) ; + end if ; + end procedure AlertIfNotEqual ; + + + ------------------------------------------------------------ + -- AlertIfNotEqual without AlertLogID + ------------------------------------------------------------ + procedure AlertIfNotEqual( L, R : std_logic ; Message : string ; Level : AlertType := ERROR ) is + ------------------------------------------------------------ + begin + if L ?/= R then + AlertLogStruct.Alert(ALERT_DEFAULT_ID, Message & " L /= R, L = " & to_string(L) & " R = " & to_string(R), Level) ; + end if ; + end procedure AlertIfNotEqual ; + + ------------------------------------------------------------ + procedure AlertIfNotEqual( L, R : std_logic_vector ; Message : string ; Level : AlertType := ERROR ) is + ------------------------------------------------------------ + begin + if L ?/= R then + AlertLogStruct.Alert(ALERT_DEFAULT_ID, Message & " L /= R, L = " & to_string(L) & " R = " & to_string(R), Level) ; + end if ; + end procedure AlertIfNotEqual ; + + ------------------------------------------------------------ + procedure AlertIfNotEqual( L, R : unsigned ; Message : string ; Level : AlertType := ERROR ) is + ------------------------------------------------------------ + begin + if L ?/= R then + AlertLogStruct.Alert(ALERT_DEFAULT_ID, Message & " L /= R, L = " & to_string(L) & " R = " & to_string(R), Level) ; + end if ; + end procedure AlertIfNotEqual ; + + ------------------------------------------------------------ + procedure AlertIfNotEqual( L, R : signed ; Message : string ; Level : AlertType := ERROR ) is + ------------------------------------------------------------ + begin + if L ?/= R then + AlertLogStruct.Alert(ALERT_DEFAULT_ID, Message & " L /= R, L = " & to_string(L) & " R = " & to_string(R), Level) ; + end if ; + end procedure AlertIfNotEqual ; + + ------------------------------------------------------------ + procedure AlertIfNotEqual( L, R : integer ; Message : string ; Level : AlertType := ERROR ) is + ------------------------------------------------------------ + begin + if L /= R then + AlertLogStruct.Alert(ALERT_DEFAULT_ID, Message & " L /= R, L = " & to_string(L) & " R = " & to_string(R), Level) ; + end if ; + end procedure AlertIfNotEqual ; + + ------------------------------------------------------------ + procedure AlertIfNotEqual( L, R : real ; Message : string ; Level : AlertType := ERROR ) is + ------------------------------------------------------------ + begin + if L /= R then + AlertLogStruct.Alert(ALERT_DEFAULT_ID, Message & " L /= R, L = " & to_string(L, 4) & " R = " & to_string(R, 4), Level) ; + end if ; + end procedure AlertIfNotEqual ; + + ------------------------------------------------------------ + procedure AlertIfNotEqual( L, R : character ; Message : string ; Level : AlertType := ERROR ) is + ------------------------------------------------------------ + begin + if L /= R then + AlertLogStruct.Alert(ALERT_DEFAULT_ID, Message & " L /= R, L = " & L & " R = " & R, Level) ; + end if ; + end procedure AlertIfNotEqual ; + + ------------------------------------------------------------ + procedure AlertIfNotEqual( L, R : string ; Message : string ; Level : AlertType := ERROR ) is + ------------------------------------------------------------ + begin + if L /= R then + AlertLogStruct.Alert(ALERT_DEFAULT_ID, Message & " L /= R, L = " & L & " R = " & R, Level) ; + end if ; + end procedure AlertIfNotEqual ; + + ------------------------------------------------------------ + procedure AlertIfNotEqual( L, R : time ; Message : string ; Level : AlertType := ERROR ) is + ------------------------------------------------------------ + begin + if L /= R then + AlertLogStruct.Alert(ALERT_DEFAULT_ID, Message & " L /= R, L = " & to_string(L) & " R = " & to_string(R), Level) ; + end if ; + end procedure AlertIfNotEqual ; + + + ------------------------------------------------------------ + -- Local + procedure LocalAlertIfDiff (AlertLogID : AlertLogIDType ; file File1, File2 : text; Message : string ; Level : AlertType ; Valid : out boolean ) is + -- Simple diff. + ------------------------------------------------------------ + variable Buf1, Buf2 : line ; + variable File1Done, File2Done : boolean ; + variable LineCount : integer := 0 ; + begin + ReadLoop : loop + File1Done := EndFile(File1) ; + File2Done := EndFile(File2) ; + exit ReadLoop when File1Done or File2Done ; + + ReadLine(File1, Buf1) ; + ReadLine(File2, Buf2) ; + LineCount := LineCount + 1 ; + + if Buf1.all /= Buf2.all then + AlertLogStruct.Alert(AlertLogID , Message & " File miscompare on line " & to_string(LineCount), Level) ; + exit ReadLoop ; + end if ; + end loop ReadLoop ; + if File1Done /= File2Done then + if not File1Done then + AlertLogStruct.Alert(AlertLogID , Message & " File1 longer than File2 " & to_string(LineCount), Level) ; + end if ; + if not File2Done then + AlertLogStruct.Alert(AlertLogID , Message & " File2 longer than File1 " & to_string(LineCount), Level) ; + end if ; + end if; + if File1Done and File2Done then + Valid := TRUE ; + else + Valid := FALSE ; + end if ; + end procedure LocalAlertIfDiff ; + + ------------------------------------------------------------ + -- Local + procedure LocalAlertIfDiff (AlertLogID : AlertLogIDType ; Name1, Name2 : string; Message : string ; Level : AlertType ; Valid : out boolean ) is + -- Open files and call AlertIfDiff[text, ...] + ------------------------------------------------------------ + file FileID1, FileID2 : text ; + variable status1, status2 : file_open_status ; + begin + Valid := FALSE ; + file_open(status1, FileID1, Name1, READ_MODE) ; + file_open(status2, FileID2, Name2, READ_MODE) ; + if status1 = OPEN_OK and status2 = OPEN_OK then + LocalAlertIfDiff (AlertLogID, FileID1, FileID2, Message & " " & Name1 & " /= " & Name2 & ", ", Level, Valid) ; + else + if status1 /= OPEN_OK then + AlertLogStruct.Alert(AlertLogID , Message & " File, " & Name1 & ", did not open", Level) ; + end if ; + if status2 /= OPEN_OK then + AlertLogStruct.Alert(AlertLogID , Message & " File, " & Name2 & ", did not open", Level) ; + end if ; + end if; + end procedure LocalAlertIfDiff ; + + ------------------------------------------------------------ + procedure AlertIfDiff (AlertLogID : AlertLogIDType ; Name1, Name2 : string; Message : string := "" ; Level : AlertType := ERROR ) is + -- Open files and call AlertIfDiff[text, ...] + ------------------------------------------------------------ + variable Valid : boolean ; + begin + LocalAlertIfDiff (AlertLogID, Name1, Name2, Message, Level, Valid) ; + end procedure AlertIfDiff ; + + ------------------------------------------------------------ + procedure AlertIfDiff (Name1, Name2 : string; Message : string := "" ; Level : AlertType := ERROR ) is + ------------------------------------------------------------ + variable Valid : boolean ; + begin + LocalAlertIfDiff (ALERT_DEFAULT_ID, Name1, Name2, Message, Level, Valid) ; + end procedure AlertIfDiff ; + + ------------------------------------------------------------ + procedure AlertIfDiff (AlertLogID : AlertLogIDType ; file File1, File2 : text; Message : string := "" ; Level : AlertType := ERROR ) is + -- Simple diff. + ------------------------------------------------------------ + variable Valid : boolean ; + begin + LocalAlertIfDiff (AlertLogID, File1, File2, Message, Level, Valid ) ; + end procedure AlertIfDiff ; + + ------------------------------------------------------------ + procedure AlertIfDiff (file File1, File2 : text; Message : string := "" ; Level : AlertType := ERROR ) is + ------------------------------------------------------------ + variable Valid : boolean ; + begin + LocalAlertIfDiff (ALERT_DEFAULT_ID, File1, File2, Message, Level, Valid ) ; + end procedure AlertIfDiff ; + + ------------------------------------------------------------ + procedure AffirmIf( + ------------------------------------------------------------ + AlertLogID : AlertLogIDType ; + condition : boolean ; + ReceivedMessage : string ; + ExpectedMessage : string ; + Enable : boolean := FALSE -- override internal enable + ) is + begin + AlertLogStruct.IncAffirmCount ; -- increment check count + if condition then + -- passed + AlertLogStruct.Log(AlertLogID, ReceivedMessage, PASSED, Enable) ; +-- AlertLogStruct.IncAffirmPassCount ; -- increment pass & check count + else + AlertLogStruct.Alert(AlertLogID, ReceivedMessage & ExpectedMessage, ERROR) ; + end if ; + end procedure AffirmIf ; + + ------------------------------------------------------------ + procedure AffirmIf( condition : boolean ; ReceivedMessage, ExpectedMessage : string ; Enable : boolean := FALSE ) is + ------------------------------------------------------------ + begin + AffirmIf(ALERT_DEFAULT_ID, condition, ReceivedMessage, ExpectedMessage, Enable) ; + end procedure AffirmIf ; + + ------------------------------------------------------------ + impure function AffirmIf( AlertLogID : AlertLogIDType ; condition : boolean ; ReceivedMessage, ExpectedMessage : string ; Enable : boolean := FALSE ) return boolean is + ------------------------------------------------------------ + begin + AffirmIf(AlertLogID, condition, ReceivedMessage, ExpectedMessage, Enable) ; + return condition ; + end function AffirmIf ; + + ------------------------------------------------------------ + impure function AffirmIf( condition : boolean ; ReceivedMessage, ExpectedMessage : string ; Enable : boolean := FALSE ) return boolean is + ------------------------------------------------------------ + begin + AffirmIf(ALERT_DEFAULT_ID, condition, ReceivedMessage, ExpectedMessage, Enable) ; + return condition ; + end function AffirmIf ; + + + ------------------------------------------------------------ + procedure AffirmIf( + ------------------------------------------------------------ + AlertLogID : AlertLogIDType ; + condition : boolean ; + Message : string ; + Enable : boolean := FALSE -- override internal enable + ) is + begin + AlertLogStruct.IncAffirmCount ; -- increment check count + if condition then + -- passed + AlertLogStruct.Log(AlertLogID, Message, PASSED, Enable) ; +-- AlertLogStruct.IncAffirmPassCount ; -- increment pass & check count + else + AlertLogStruct.Alert(AlertLogID, Message, ERROR) ; + end if ; + end procedure AffirmIf ; + + ------------------------------------------------------------ + procedure AffirmIf(condition : boolean ; Message : string ; Enable : boolean := FALSE) is + ------------------------------------------------------------ + begin + AffirmIf(ALERT_DEFAULT_ID, condition, Message, Enable) ; + end procedure AffirmIf; + + ------------------------------------------------------------ + -- useful in a loop: exit when AffirmIf( ID, not ReadValid, "Read Failed") ; + impure function AffirmIf( AlertLogID : AlertLogIDType ; condition : boolean ; Message : string ; Enable : boolean := FALSE ) return boolean is + ------------------------------------------------------------ + begin + AffirmIf(AlertLogID, condition, Message, Enable) ; + return condition ; + end function AffirmIf ; + + ------------------------------------------------------------ + impure function AffirmIf( condition : boolean ; Message : string ; Enable : boolean := FALSE ) return boolean is + ------------------------------------------------------------ + begin + AffirmIf(ALERT_DEFAULT_ID, condition, Message, Enable) ; + return condition ; + end function AffirmIf ; + + ------------------------------------------------------------ + ------------------------------------------------------------ + procedure AffirmIfNot( AlertLogID : AlertLogIDType ; condition : boolean ; ReceivedMessage, ExpectedMessage : string ; Enable : boolean := FALSE ) is + ------------------------------------------------------------ + begin + AffirmIf(AlertLogID, not condition, ReceivedMessage, ExpectedMessage, Enable) ; + end procedure AffirmIfNot ; + + ------------------------------------------------------------ + procedure AffirmIfNot( condition : boolean ; ReceivedMessage, ExpectedMessage : string ; Enable : boolean := FALSE ) is + ------------------------------------------------------------ + begin + AffirmIf(ALERT_DEFAULT_ID, not condition, ReceivedMessage, ExpectedMessage, Enable) ; + end procedure AffirmIfNot ; + + ------------------------------------------------------------ + -- useful in a loop: exit when AffirmIfNot( not ReadValid, failure, "Read Failed") ; + impure function AffirmIfNot( AlertLogID : AlertLogIDType ; condition : boolean ; ReceivedMessage, ExpectedMessage : string ; Enable : boolean := FALSE ) return boolean is + ------------------------------------------------------------ + begin + AffirmIf(AlertLogID, not condition, ReceivedMessage, ExpectedMessage, Enable) ; + return not condition ; + end function AffirmIfNot ; + + ------------------------------------------------------------ + impure function AffirmIfNot( condition : boolean ; ReceivedMessage, ExpectedMessage : string ; Enable : boolean := FALSE ) return boolean is + ------------------------------------------------------------ + begin + AffirmIf(ALERT_DEFAULT_ID, not condition, ReceivedMessage, ExpectedMessage, Enable) ; + return not condition ; + end function AffirmIfNot ; + + ------------------------------------------------------------ + procedure AffirmIfNot( AlertLogID : AlertLogIDType ; condition : boolean ; Message : string ; Enable : boolean := FALSE ) is + ------------------------------------------------------------ + begin + AffirmIf(AlertLogID, not condition, Message, Enable) ; + end procedure AffirmIfNot ; + + ------------------------------------------------------------ + procedure AffirmIfNot( condition : boolean ; Message : string ; Enable : boolean := FALSE ) is + ------------------------------------------------------------ + begin + AffirmIf(ALERT_DEFAULT_ID, not condition, Message, Enable) ; + end procedure AffirmIfNot ; + + ------------------------------------------------------------ + -- useful in a loop: exit when AffirmIfNot( not ReadValid, failure, "Read Failed") ; + impure function AffirmIfNot( AlertLogID : AlertLogIDType ; condition : boolean ; Message : string ; Enable : boolean := FALSE ) return boolean is + ------------------------------------------------------------ + begin + AffirmIf(AlertLogID, not condition, Message, Enable) ; + return not condition ; + end function AffirmIfNot ; + + ------------------------------------------------------------ + impure function AffirmIfNot( condition : boolean ; Message : string ; Enable : boolean := FALSE ) return boolean is + ------------------------------------------------------------ + begin + AffirmIf(ALERT_DEFAULT_ID, not condition, Message, Enable) ; + return not condition ; + end function AffirmIfNot ; + + + ------------------------------------------------------------ + ------------------------------------------------------------ + procedure AffirmPassed( AlertLogID : AlertLogIDType ; Message : string ; Enable : boolean := FALSE ) is + ------------------------------------------------------------ + begin + AffirmIf(AlertLogID, TRUE, Message, Enable) ; + end procedure AffirmPassed ; + + ------------------------------------------------------------ + procedure AffirmPassed( Message : string ; Enable : boolean := FALSE ) is + ------------------------------------------------------------ + begin + AffirmIf(ALERT_DEFAULT_ID, TRUE, Message, Enable) ; + end procedure AffirmPassed ; + + ------------------------------------------------------------ + procedure AffirmError( AlertLogID : AlertLogIDType ; Message : string ) is + ------------------------------------------------------------ + begin + AffirmIf(AlertLogID, FALSE, Message, FALSE) ; + end procedure AffirmError ; + + ------------------------------------------------------------ + procedure AffirmError( Message : string ) is + ------------------------------------------------------------ + begin + AffirmIf(ALERT_DEFAULT_ID, FALSE, Message, FALSE) ; + end procedure AffirmError ; + + -- With AlertLogID + ------------------------------------------------------------ + procedure AffirmIfEqual( AlertLogID : AlertLogIDType ; Received, Expected : std_logic ; Message : string := "" ; Enable : boolean := FALSE ) is + ------------------------------------------------------------ + begin + AffirmIf(AlertLogID, ??(Received ?= Expected), + Message & " Received : " & to_string(Received), + " ?= Expected : " & to_string(Expected), + Enable) ; + end procedure AffirmIfEqual ; + + ------------------------------------------------------------ + procedure AffirmIfEqual( AlertLogID : AlertLogIDType ; Received, Expected : std_logic_vector ; Message : string := "" ; Enable : boolean := FALSE ) is + ------------------------------------------------------------ + begin + AffirmIf(AlertLogID, ??(Received ?= Expected), + Message & " Received : " & to_hstring(Received), + " ?= Expected : " & to_hstring(Expected), + Enable) ; + end procedure AffirmIfEqual ; + + ------------------------------------------------------------ + procedure AffirmIfEqual( AlertLogID : AlertLogIDType ; Received, Expected : unsigned ; Message : string := "" ; Enable : boolean := FALSE ) is + ------------------------------------------------------------ + begin + AffirmIf(AlertLogID, ??(Received ?= Expected), + Message & " Received : " & to_hstring(Received), + " ?= Expected : " & to_hstring(Expected), + Enable) ; + end procedure AffirmIfEqual ; + + ------------------------------------------------------------ + procedure AffirmIfEqual( AlertLogID : AlertLogIDType ; Received, Expected : signed ; Message : string := "" ; Enable : boolean := FALSE ) is + ------------------------------------------------------------ + begin + AffirmIf(AlertLogID, ??(Received ?= Expected), + Message & " Received : " & to_hstring(Received), + " ?= Expected : " & to_hstring(Expected), + Enable) ; + end procedure AffirmIfEqual ; + + ------------------------------------------------------------ + procedure AffirmIfEqual( AlertLogID : AlertLogIDType ; Received, Expected : integer ; Message : string := "" ; Enable : boolean := FALSE ) is + ------------------------------------------------------------ + begin + AffirmIf(AlertLogID, Received = Expected, + Message & " Received : " & to_string(Received), + " = Expected : " & to_string(Expected), + Enable) ; + end procedure AffirmIfEqual ; + + ------------------------------------------------------------ + procedure AffirmIfEqual( AlertLogID : AlertLogIDType ; Received, Expected : real ; Message : string := "" ; Enable : boolean := FALSE ) is + ------------------------------------------------------------ + begin + AffirmIf(AlertLogID, Received = Expected, + Message & " Received : " & to_string(Received, 4), + " = Expected : " & to_string(Expected, 4), + Enable) ; + end procedure AffirmIfEqual ; + + ------------------------------------------------------------ + procedure AffirmIfEqual( AlertLogID : AlertLogIDType ; Received, Expected : character ; Message : string := "" ; Enable : boolean := FALSE ) is + ------------------------------------------------------------ + begin + AffirmIf(AlertLogID, Received = Expected, + Message & " Received : " & to_string(Received), + " = Expected : " & to_string(Expected), + Enable) ; + end procedure AffirmIfEqual ; + + ------------------------------------------------------------ + procedure AffirmIfEqual( AlertLogID : AlertLogIDType ; Received, Expected : string ; Message : string := "" ; Enable : boolean := FALSE ) is + ------------------------------------------------------------ + begin + AffirmIf(AlertLogID, Received = Expected, + Message & " Received : " & Received, + " = Expected : " & Expected, + Enable) ; + end procedure AffirmIfEqual ; + + ------------------------------------------------------------ + procedure AffirmIfEqual( AlertLogID : AlertLogIDType ; Received, Expected : time ; Message : string := "" ; Enable : boolean := FALSE ) is + ------------------------------------------------------------ + begin + AffirmIf(AlertLogID, Received = Expected, + Message & " Received : " & to_string(Received), + " = Expected : " & to_string(Expected), + Enable) ; + end procedure AffirmIfEqual ; + + -- Without AlertLogID + ------------------------------------------------------------ + procedure AffirmIfEqual( Received, Expected : std_logic ; Message : string := "" ; Enable : boolean := FALSE ) is + ------------------------------------------------------------ + begin + AffirmIf(ALERT_DEFAULT_ID, ??(Received ?= Expected), + Message & " Received : " & to_string(Received), + " ?= Expected : " & to_string(Expected), + Enable) ; + end procedure AffirmIfEqual ; + + ------------------------------------------------------------ + procedure AffirmIfEqual( Received, Expected : std_logic_vector ; Message : string := "" ; Enable : boolean := FALSE ) is + ------------------------------------------------------------ + begin + AffirmIf(ALERT_DEFAULT_ID, ??(Received ?= Expected), + Message & " Received : " & to_string(Received), + " ?= Expected : " & to_string(Expected), + Enable) ; + end procedure AffirmIfEqual ; + + ------------------------------------------------------------ + procedure AffirmIfEqual( Received, Expected : unsigned ; Message : string := "" ; Enable : boolean := FALSE ) is + ------------------------------------------------------------ + begin + AffirmIf(ALERT_DEFAULT_ID, ??(Received ?= Expected), + Message & " Received : " & to_string(Received), + " ?= Expected : " & to_string(Expected), + Enable) ; + end procedure AffirmIfEqual ; + + ------------------------------------------------------------ + procedure AffirmIfEqual( Received, Expected : signed ; Message : string := "" ; Enable : boolean := FALSE ) is + ------------------------------------------------------------ + begin + AffirmIf(ALERT_DEFAULT_ID, ??(Received ?= Expected), + Message & " Received : " & to_string(Received), + " ?= Expected : " & to_string(Expected), + Enable) ; + end procedure AffirmIfEqual ; + + ------------------------------------------------------------ + procedure AffirmIfEqual( Received, Expected : integer ; Message : string := "" ; Enable : boolean := FALSE ) is + ------------------------------------------------------------ + begin + AffirmIf(ALERT_DEFAULT_ID, Received = Expected, + Message & " Received : " & to_string(Received), + " = Expected : " & to_string(Expected), + Enable) ; + end procedure AffirmIfEqual ; + + ------------------------------------------------------------ + procedure AffirmIfEqual( Received, Expected : real ; Message : string := "" ; Enable : boolean := FALSE ) is + ------------------------------------------------------------ + begin + AffirmIf(ALERT_DEFAULT_ID, Received = Expected, + Message & " Received : " & to_string(Received, 4), + " = Expected : " & to_string(Expected, 4), + Enable) ; + end procedure AffirmIfEqual ; + + ------------------------------------------------------------ + procedure AffirmIfEqual( Received, Expected : character ; Message : string := "" ; Enable : boolean := FALSE ) is + ------------------------------------------------------------ + begin + AffirmIf(ALERT_DEFAULT_ID, Received = Expected, + Message & " Received : " & to_string(Received), + " = Expected : " & to_string(Expected), + Enable) ; + end procedure AffirmIfEqual ; + + ------------------------------------------------------------ + procedure AffirmIfEqual( Received, Expected : string ; Message : string := "" ; Enable : boolean := FALSE ) is + ------------------------------------------------------------ + begin + AffirmIf(ALERT_DEFAULT_ID, Received = Expected, + Message & " Received : " & Received, + " = Expected : " & Expected, + Enable) ; + end procedure AffirmIfEqual ; + + ------------------------------------------------------------ + procedure AffirmIfEqual( Received, Expected : time ; Message : string := "" ; Enable : boolean := FALSE ) is + ------------------------------------------------------------ + begin + AffirmIf(ALERT_DEFAULT_ID, Received = Expected, + Message & " Received : " & to_string(Received), + " = Expected : " & to_string(Expected), + Enable) ; + end procedure AffirmIfEqual ; + + ------------------------------------------------------------ + procedure AffirmIfDiff (AlertLogID : AlertLogIDType ; Name1, Name2 : string; Message : string := "" ; Enable : boolean := FALSE ) is + -- Open files and call AffirmIfDiff[text, ...] + ------------------------------------------------------------ + variable Valid : boolean ; + begin + LocalAlertIfDiff (AlertLogID, Name1, Name2, Message, ERROR, Valid) ; + if Valid then + AlertLogStruct.Log(AlertLogID, Message & " " & Name1 & " = " & Name2, PASSED, Enable) ; + end if ; + end procedure AffirmIfDiff ; + + ------------------------------------------------------------ + procedure AffirmIfDiff (Name1, Name2 : string; Message : string := "" ; Enable : boolean := FALSE ) is + ------------------------------------------------------------ + variable Valid : boolean ; + begin + LocalAlertIfDiff (ALERT_DEFAULT_ID, Name1, Name2, Message, ERROR, Valid) ; + if Valid then + AlertLogStruct.Log(ALERT_DEFAULT_ID, Message & " " & Name1 & " = " & Name2, PASSED, Enable) ; + end if ; + end procedure AffirmIfDiff ; + + ------------------------------------------------------------ + procedure AffirmIfDiff (AlertLogID : AlertLogIDType ; file File1, File2 : text; Message : string := "" ; Enable : boolean := FALSE ) is + -- Simple diff. + ------------------------------------------------------------ + variable Valid : boolean ; + begin + LocalAlertIfDiff (AlertLogID, File1, File2, Message, ERROR, Valid ) ; + if Valid then + AlertLogStruct.Log(AlertLogID, Message, PASSED, Enable) ; + end if ; + end procedure AffirmIfDiff ; + + ------------------------------------------------------------ + procedure AffirmIfDiff (file File1, File2 : text; Message : string := "" ; Enable : boolean := FALSE ) is + ------------------------------------------------------------ + variable Valid : boolean ; + begin + LocalAlertIfDiff (ALERT_DEFAULT_ID, File1, File2, Message, ERROR, Valid ) ; + if Valid then + AlertLogStruct.Log(ALERT_DEFAULT_ID, Message, PASSED, Enable) ; + end if ; + end procedure AffirmIfDiff ; + + ------------------------------------------------------------ + procedure SetAlertLogJustify is + ------------------------------------------------------------ + begin + AlertLogStruct.SetJustify ; + end procedure SetAlertLogJustify ; + + ------------------------------------------------------------ + procedure ReportAlerts ( Name : String ; AlertCount : AlertCountType ) is + ------------------------------------------------------------ + begin + AlertLogStruct.ReportAlerts(Name, AlertCount) ; + end procedure ReportAlerts ; + + ------------------------------------------------------------ + procedure ReportAlerts ( Name : string := OSVVM_STRING_INIT_PARM_DETECT ; AlertLogID : AlertLogIDType := ALERTLOG_BASE_ID ; ExternalErrors : AlertCountType := (others => 0) ) is + ------------------------------------------------------------ + begin + AlertLogStruct.ReportAlerts(Name, AlertLogID, ExternalErrors, TRUE) ; + end procedure ReportAlerts ; + + ------------------------------------------------------------ + procedure ReportNonZeroAlerts ( Name : string := OSVVM_STRING_INIT_PARM_DETECT ; AlertLogID : AlertLogIDType := ALERTLOG_BASE_ID ; ExternalErrors : AlertCountType := (others => 0) ) is + ------------------------------------------------------------ + begin + AlertLogStruct.ReportAlerts(Name, AlertLogID, ExternalErrors, FALSE) ; + end procedure ReportNonZeroAlerts ; + + ------------------------------------------------------------ + procedure ClearAlerts is + ------------------------------------------------------------ + begin + AlertLogStruct.ClearAlerts ; + end procedure ClearAlerts ; + + ------------------------------------------------------------ + function "ABS" (L : AlertCountType) return AlertCountType is + ------------------------------------------------------------ + variable Result : AlertCountType ; + begin + Result(FAILURE) := ABS( L(FAILURE) ) ; + Result(ERROR) := ABS( L(ERROR) ) ; + Result(WARNING) := ABS( L(WARNING) ); + return Result ; + end function "ABS" ; + + ------------------------------------------------------------ + function "+" (L, R : AlertCountType) return AlertCountType is + ------------------------------------------------------------ + variable Result : AlertCountType ; + begin + Result(FAILURE) := L(FAILURE) + R(FAILURE) ; + Result(ERROR) := L(ERROR) + R(ERROR) ; + Result(WARNING) := L(WARNING) + R(WARNING) ; + return Result ; + end function "+" ; + + ------------------------------------------------------------ + function "-" (L, R : AlertCountType) return AlertCountType is + ------------------------------------------------------------ + variable Result : AlertCountType ; + begin + Result(FAILURE) := L(FAILURE) - R(FAILURE) ; + Result(ERROR) := L(ERROR) - R(ERROR) ; + Result(WARNING) := L(WARNING) - R(WARNING) ; + return Result ; + end function "-" ; + + ------------------------------------------------------------ + function "-" (R : AlertCountType) return AlertCountType is + ------------------------------------------------------------ + variable Result : AlertCountType ; + begin + Result(FAILURE) := - R(FAILURE) ; + Result(ERROR) := - R(ERROR) ; + Result(WARNING) := - R(WARNING) ; + return Result ; + end function "-" ; + + ------------------------------------------------------------ + impure function SumAlertCount(AlertCount: AlertCountType) return integer is + ------------------------------------------------------------ + begin + -- Using ABS ensures correct expected error handling. + return abs(AlertCount(FAILURE)) + abs(AlertCount(ERROR)) + abs(AlertCount(WARNING)) ; + end function SumAlertCount ; + + ------------------------------------------------------------ + impure function GetAlertCount(AlertLogID : AlertLogIDType := ALERTLOG_BASE_ID) return AlertCountType is + ------------------------------------------------------------ + begin + return AlertLogStruct.GetAlertCount(AlertLogID) ; + end function GetAlertCount ; + + ------------------------------------------------------------ + impure function GetAlertCount(AlertLogID : AlertLogIDType := ALERTLOG_BASE_ID) return integer is + ------------------------------------------------------------ + begin + return SumAlertCount(AlertLogStruct.GetAlertCount(AlertLogID)) ; + end function GetAlertCount ; + + ------------------------------------------------------------ + impure function GetEnabledAlertCount(AlertLogID : AlertLogIDType := ALERTLOG_BASE_ID) return AlertCountType is + ------------------------------------------------------------ + begin + return AlertLogStruct.GetEnabledAlertCount(AlertLogID) ; + end function GetEnabledAlertCount ; + + ------------------------------------------------------------ + impure function GetEnabledAlertCount(AlertLogID : AlertLogIDType := ALERTLOG_BASE_ID) return integer is + ------------------------------------------------------------ + begin + return SumAlertCount(AlertLogStruct.GetEnabledAlertCount(AlertLogID)) ; + end function GetEnabledAlertCount ; + + ------------------------------------------------------------ + impure function GetDisabledAlertCount return AlertCountType is + ------------------------------------------------------------ + begin + return AlertLogStruct.GetDisabledAlertCount ; + end function GetDisabledAlertCount ; + + ------------------------------------------------------------ + impure function GetDisabledAlertCount return integer is + ------------------------------------------------------------ + begin + return SumAlertCount(AlertLogStruct.GetDisabledAlertCount) ; + end function GetDisabledAlertCount ; + + ------------------------------------------------------------ + impure function GetDisabledAlertCount(AlertLogID: AlertLogIDType) return AlertCountType is + ------------------------------------------------------------ + begin + return AlertLogStruct.GetDisabledAlertCount(AlertLogID) ; + end function GetDisabledAlertCount ; + + ------------------------------------------------------------ + impure function GetDisabledAlertCount(AlertLogID: AlertLogIDType) return integer is + ------------------------------------------------------------ + begin + return SumAlertCount(AlertLogStruct.GetDisabledAlertCount(AlertLogID)) ; + end function GetDisabledAlertCount ; + + ------------------------------------------------------------ + procedure Log( + AlertLogID : AlertLogIDType ; + Message : string ; + Level : LogType := ALWAYS ; + Enable : boolean := FALSE -- override internal enable + ) is + begin + AlertLogStruct.Log(AlertLogID, Message, Level, Enable) ; + end procedure log ; + + ------------------------------------------------------------ + procedure Log( Message : string ; Level : LogType := ALWAYS ; Enable : boolean := FALSE) is + ------------------------------------------------------------ + begin + AlertLogStruct.Log(LOG_DEFAULT_ID, Message, Level, Enable) ; + end procedure log ; + + ------------------------------------------------------------ + procedure SetAlertLogName(Name : string ) is + ------------------------------------------------------------ + begin + AlertLogStruct.SetAlertLogName(Name) ; + end procedure SetAlertLogName ; + + ------------------------------------------------------------ + impure function GetAlertLogName(AlertLogID : AlertLogIDType := ALERTLOG_BASE_ID) return string is + ------------------------------------------------------------ + begin + return AlertLogStruct.GetAlertLogName(AlertLogID) ; + end GetAlertLogName ; + + ------------------------------------------------------------ + procedure DeallocateAlertLogStruct is + ------------------------------------------------------------ + begin + AlertLogStruct.Deallocate ; + end procedure DeallocateAlertLogStruct ; + + ------------------------------------------------------------ + procedure InitializeAlertLogStruct is + ------------------------------------------------------------ + begin + AlertLogStruct.Initialize ; + end procedure InitializeAlertLogStruct ; + + ------------------------------------------------------------ + impure function FindAlertLogID(Name : string ) return AlertLogIDType is + ------------------------------------------------------------ + begin + return AlertLogStruct.FindAlertLogID(Name) ; + end function FindAlertLogID ; + + ------------------------------------------------------------ + impure function FindAlertLogID(Name : string ; ParentID : AlertLogIDType) return AlertLogIDType is + ------------------------------------------------------------ + begin + return AlertLogStruct.FindAlertLogID(Name, ParentID) ; + end function FindAlertLogID ; + + ------------------------------------------------------------ + impure function GetAlertLogID(Name : string ; ParentID : AlertLogIDType := ALERTLOG_BASE_ID ; CreateHierarchy : Boolean := TRUE) return AlertLogIDType is + ------------------------------------------------------------ + begin + return AlertLogStruct.GetAlertLogID(Name, ParentID, CreateHierarchy ) ; + end function GetAlertLogID ; + + ------------------------------------------------------------ + impure function GetAlertLogParentID(AlertLogID : AlertLogIDType) return AlertLogIDType is + ------------------------------------------------------------ + begin + return AlertLogStruct.GetAlertLogParentID(AlertLogID) ; + end function GetAlertLogParentID ; + + ------------------------------------------------------------ + procedure SetGlobalAlertEnable (A : boolean := TRUE) is + ------------------------------------------------------------ + begin + AlertLogStruct.SetGlobalAlertEnable(A) ; + end procedure SetGlobalAlertEnable ; + + ------------------------------------------------------------ + -- Set using constant. Set before code runs. + impure function SetGlobalAlertEnable (A : boolean := TRUE) return boolean is + ------------------------------------------------------------ + begin + AlertLogStruct.SetGlobalAlertEnable(A) ; + return A ; + end function SetGlobalAlertEnable ; + + ------------------------------------------------------------ + impure function GetGlobalAlertEnable return boolean is + ------------------------------------------------------------ + begin + return AlertLogStruct.GetGlobalAlertEnable ; + end function GetGlobalAlertEnable ; + + ------------------------------------------------------------ + procedure IncAffirmCount is + ------------------------------------------------------------ + begin + AlertLogStruct.IncAffirmCount ; + end procedure IncAffirmCount ; + + ------------------------------------------------------------ + impure function GetAffirmCount return natural is + ------------------------------------------------------------ + begin + return AlertLogStruct.GetAffirmCount ; + end function GetAffirmCount ; + +--?? ------------------------------------------------------------ +--?? procedure IncAffirmPassCount is +--?? ------------------------------------------------------------ +--?? begin +--?? AlertLogStruct.IncAffirmPassCount ; +--?? end procedure IncAffirmPassCount ; +--?? +--?? ------------------------------------------------------------ +--?? impure function GetAffirmPassCount return natural is +--?? ------------------------------------------------------------ +--?? begin +--?? return AlertLogStruct.GetAffirmPassCount ; +--?? end function GetAffirmPassCount ; + + ------------------------------------------------------------ + procedure SetAlertStopCount(AlertLogID : AlertLogIDType ; Level : AlertType ; Count : integer) is + ------------------------------------------------------------ + begin + AlertLogStruct.SetAlertStopCount(AlertLogID, Level, Count) ; + end procedure SetAlertStopCount ; + + ------------------------------------------------------------ + procedure SetAlertStopCount(Level : AlertType ; Count : integer) is + ------------------------------------------------------------ + begin + AlertLogStruct.SetAlertStopCount(ALERTLOG_BASE_ID, Level, Count) ; + end procedure SetAlertStopCount ; + + ------------------------------------------------------------ + impure function GetAlertStopCount(AlertLogID : AlertLogIDType ; Level : AlertType) return integer is + ------------------------------------------------------------ + begin + return AlertLogStruct.GetAlertStopCount(AlertLogID, Level) ; + end function GetAlertStopCount ; + + ------------------------------------------------------------ + impure function GetAlertStopCount(Level : AlertType) return integer is + ------------------------------------------------------------ + begin + return AlertLogStruct.GetAlertStopCount(ALERTLOG_BASE_ID, Level) ; + end function GetAlertStopCount ; + + ------------------------------------------------------------ + procedure SetAlertEnable(Level : AlertType ; Enable : boolean) is + ------------------------------------------------------------ + begin + AlertLogStruct.SetAlertEnable(Level, Enable) ; + end procedure SetAlertEnable ; + + ------------------------------------------------------------ + procedure SetAlertEnable(AlertLogID : AlertLogIDType ; Level : AlertType ; Enable : boolean ; DescendHierarchy : boolean := TRUE) is + ------------------------------------------------------------ + begin + AlertLogStruct.SetAlertEnable(AlertLogID, Level, Enable, DescendHierarchy) ; + end procedure SetAlertEnable ; + + ------------------------------------------------------------ + impure function GetAlertEnable(AlertLogID : AlertLogIDType ; Level : AlertType) return boolean is + ------------------------------------------------------------ + begin + return AlertLogStruct.GetAlertEnable(AlertLogID, Level) ; + end function GetAlertEnable ; + + ------------------------------------------------------------ + impure function GetAlertEnable(Level : AlertType) return boolean is + ------------------------------------------------------------ + begin + return AlertLogStruct.GetAlertEnable(ALERT_DEFAULT_ID, Level) ; + end function GetAlertEnable ; + + ------------------------------------------------------------ + procedure SetLogEnable(Level : LogType ; Enable : boolean) is + ------------------------------------------------------------ + begin + AlertLogStruct.SetLogEnable(Level, Enable) ; + end procedure SetLogEnable ; + + ------------------------------------------------------------ + procedure SetLogEnable(AlertLogID : AlertLogIDType ; Level : LogType ; Enable : boolean ; DescendHierarchy : boolean := TRUE) is + ------------------------------------------------------------ + begin + AlertLogStruct.SetLogEnable(AlertLogID, Level, Enable, DescendHierarchy) ; + end procedure SetLogEnable ; + + ------------------------------------------------------------ + impure function GetLogEnable(AlertLogID : AlertLogIDType ; Level : LogType) return boolean is + ------------------------------------------------------------ + begin + return AlertLogStruct.GetLogEnable(AlertLogID, Level) ; + end function GetLogEnable ; + + ------------------------------------------------------------ + impure function GetLogEnable(Level : LogType) return boolean is + ------------------------------------------------------------ + begin + return AlertLogStruct.GetLogEnable(LOG_DEFAULT_ID, Level) ; + end function GetLogEnable ; + + ------------------------------------------------------------ + procedure ReportLogEnables is + ------------------------------------------------------------ + begin + AlertLogStruct.ReportLogEnables ; + end ReportLogEnables ; + + ------------------------------------------------------------ + procedure SetAlertLogOptions ( + ------------------------------------------------------------ + FailOnWarning : AlertLogOptionsType := OPT_INIT_PARM_DETECT ; + FailOnDisabledErrors : AlertLogOptionsType := OPT_INIT_PARM_DETECT ; + ReportHierarchy : AlertLogOptionsType := OPT_INIT_PARM_DETECT ; + WriteAlertLevel : AlertLogOptionsType := OPT_INIT_PARM_DETECT ; + WriteAlertName : AlertLogOptionsType := OPT_INIT_PARM_DETECT ; + WriteAlertTime : AlertLogOptionsType := OPT_INIT_PARM_DETECT ; + WriteLogLevel : AlertLogOptionsType := OPT_INIT_PARM_DETECT ; + WriteLogName : AlertLogOptionsType := OPT_INIT_PARM_DETECT ; + WriteLogTime : AlertLogOptionsType := OPT_INIT_PARM_DETECT ; + AlertPrefix : string := OSVVM_STRING_INIT_PARM_DETECT ; + LogPrefix : string := OSVVM_STRING_INIT_PARM_DETECT ; + ReportPrefix : string := OSVVM_STRING_INIT_PARM_DETECT ; + DoneName : string := OSVVM_STRING_INIT_PARM_DETECT ; + PassName : string := OSVVM_STRING_INIT_PARM_DETECT ; + FailName : string := OSVVM_STRING_INIT_PARM_DETECT + ) is + begin + AlertLogStruct.SetAlertLogOptions ( + FailOnWarning => FailOnWarning , + FailOnDisabledErrors => FailOnDisabledErrors, + ReportHierarchy => ReportHierarchy , + WriteAlertLevel => WriteAlertLevel , + WriteAlertName => WriteAlertName , + WriteAlertTime => WriteAlertTime , + WriteLogLevel => WriteLogLevel , + WriteLogName => WriteLogName , + WriteLogTime => WriteLogTime , + AlertPrefix => AlertPrefix , + LogPrefix => LogPrefix , + ReportPrefix => ReportPrefix , + DoneName => DoneName , + PassName => PassName , + FailName => FailName + ); + end procedure SetAlertLogOptions ; + + ------------------------------------------------------------ + procedure ReportAlertLogOptions is + ------------------------------------------------------------ + begin + AlertLogStruct.ReportAlertLogOptions ; + end procedure ReportAlertLogOptions ; + + ------------------------------------------------------------ + impure function GetAlertLogFailOnWarning return AlertLogOptionsType is + ------------------------------------------------------------ + begin + return AlertLogStruct.GetAlertLogFailOnWarning ; + end function GetAlertLogFailOnWarning ; + + ------------------------------------------------------------ + impure function GetAlertLogFailOnDisabledErrors return AlertLogOptionsType is + ------------------------------------------------------------ + begin + return AlertLogStruct.GetAlertLogFailOnDisabledErrors ; + end function GetAlertLogFailOnDisabledErrors ; + + ------------------------------------------------------------ + impure function GetAlertLogReportHierarchy return AlertLogOptionsType is + ------------------------------------------------------------ + begin + return AlertLogStruct.GetAlertLogReportHierarchy ; + end function GetAlertLogReportHierarchy ; + + ------------------------------------------------------------ + impure function GetAlertLogFoundReportHier return boolean is + ------------------------------------------------------------ + begin + return AlertLogStruct.GetAlertLogFoundReportHier ; + end function GetAlertLogFoundReportHier ; + + ------------------------------------------------------------ + impure function GetAlertLogFoundAlertHier return boolean is + ------------------------------------------------------------ + begin + return AlertLogStruct.GetAlertLogFoundAlertHier ; + end function GetAlertLogFoundAlertHier ; + + ------------------------------------------------------------ + impure function GetAlertLogWriteAlertLevel return AlertLogOptionsType is + ------------------------------------------------------------ + begin + return AlertLogStruct.GetAlertLogWriteAlertLevel ; + end function GetAlertLogWriteAlertLevel ; + + ------------------------------------------------------------ + impure function GetAlertLogWriteAlertName return AlertLogOptionsType is + ------------------------------------------------------------ + begin + return AlertLogStruct.GetAlertLogWriteAlertName ; + end function GetAlertLogWriteAlertName ; + + ------------------------------------------------------------ + impure function GetAlertLogWriteAlertTime return AlertLogOptionsType is + ------------------------------------------------------------ + begin + return AlertLogStruct.GetAlertLogWriteAlertTime ; + end function GetAlertLogWriteAlertTime ; + + ------------------------------------------------------------ + impure function GetAlertLogWriteLogLevel return AlertLogOptionsType is + ------------------------------------------------------------ + begin + return AlertLogStruct.GetAlertLogWriteLogLevel ; + end function GetAlertLogWriteLogLevel ; + + ------------------------------------------------------------ + impure function GetAlertLogWriteLogName return AlertLogOptionsType is + ------------------------------------------------------------ + begin + return AlertLogStruct.GetAlertLogWriteLogName ; + end function GetAlertLogWriteLogName ; + + ------------------------------------------------------------ + impure function GetAlertLogWriteLogTime return AlertLogOptionsType is + ------------------------------------------------------------ + begin + return AlertLogStruct.GetAlertLogWriteLogTime ; + end function GetAlertLogWriteLogTime ; + + ------------------------------------------------------------ + impure function GetAlertLogAlertPrefix return string is + ------------------------------------------------------------ + begin + return AlertLogStruct.GetAlertLogAlertPrefix ; + end function GetAlertLogAlertPrefix ; + + ------------------------------------------------------------ + impure function GetAlertLogLogPrefix return string is + ------------------------------------------------------------ + begin + return AlertLogStruct.GetAlertLogLogPrefix ; + end function GetAlertLogLogPrefix ; + + ------------------------------------------------------------ + impure function GetAlertLogReportPrefix return string is + ------------------------------------------------------------ + begin + return AlertLogStruct.GetAlertLogReportPrefix ; + end function GetAlertLogReportPrefix ; + + ------------------------------------------------------------ + impure function GetAlertLogDoneName return string is + ------------------------------------------------------------ + begin + return AlertLogStruct.GetAlertLogDoneName ; + end function GetAlertLogDoneName ; + + ------------------------------------------------------------ + impure function GetAlertLogPassName return string is + ------------------------------------------------------------ + begin + return AlertLogStruct.GetAlertLogPassName ; + end function GetAlertLogPassName ; + + ------------------------------------------------------------ + impure function GetAlertLogFailName return string is + ------------------------------------------------------------ + begin + return AlertLogStruct.GetAlertLogFailName ; + end function GetAlertLogFailName ; + + ------------------------------------------------------------ + function IsLogEnableType (Name : String) return boolean is + ------------------------------------------------------------ + -- type LogType is (ALWAYS, DEBUG, FINAL, INFO, PASSED) ; -- NEVER + begin + if Name = "PASSED" then return TRUE ; + elsif Name = "DEBUG" then return TRUE ; + elsif Name = "FINAL" then return TRUE ; + elsif Name = "INFO" then return TRUE ; + end if ; + return FALSE ; + end function IsLogEnableType ; + + ------------------------------------------------------------ + procedure ReadLogEnables (file AlertLogInitFile : text) is + -- Preferred Read format + -- Line 1: instance1_name log_enable log_enable log_enable + -- Line 2: instance2_name log_enable log_enable log_enable + -- when reading multiple log_enables on a line, they must be separated by a space + -- + --- Also supports alternate format from Lyle/.... + -- Line 1: instance1_name + -- Line 2: log enable + -- Line 3: instance2_name + -- Line 4: log enable + -- + ------------------------------------------------------------ + type ReadStateType is (GET_ID, GET_ENABLE) ; + variable ReadState : ReadStateType := GET_ID ; + variable buf : line ; + variable Empty : boolean ; + variable MultiLineComment : boolean := FALSE ; + variable Name : string(1 to 80) ; + variable NameLen : integer ; + variable AlertLogID : AlertLogIDType ; + variable ReadAnEnable : boolean ; + variable LogLevel : LogType ; + begin + ReadState := GET_ID ; + ReadLineLoop : while not EndFile(AlertLogInitFile) loop + ReadLine(AlertLogInitFile, buf) ; + if ReadAnEnable then + -- Read one or more enable values, next line read AlertLog name + -- Note that any newline with ReadAnEnable TRUE will result in + -- searching for another AlertLogID name - this includes multi-line comments. + ReadState := GET_ID ; + end if ; + + ReadNameLoop : loop + EmptyOrCommentLine(buf, Empty, MultiLineComment) ; + next ReadLineLoop when Empty ; + + case ReadState is + when GET_ID => + sread(buf, Name, NameLen) ; + exit ReadNameLoop when NameLen = 0 ; + AlertLogID := GetAlertLogID(Name(1 to NameLen), ALERTLOG_ID_NOT_ASSIGNED) ; + ReadState := GET_ENABLE ; + ReadAnEnable := FALSE ; + + when GET_ENABLE => + sread(buf, Name, NameLen) ; + exit ReadNameLoop when NameLen = 0 ; + ReadAnEnable := TRUE ; + if not IsLogEnableType(Name(1 to NameLen)) then + Alert(OSVVM_ALERTLOG_ID, "AlertLogPkg.ReadLogEnables: Found Invalid LogEnable: " & Name(1 to NameLen)) ; + exit ReadNameLoop ; + end if ; + LogLevel := LogType'value(Name(1 to NameLen)) ; + SetLogEnable(AlertLogID, LogLevel, TRUE) ; + end case ; + end loop ReadNameLoop ; + end loop ReadLineLoop ; + end procedure ReadLogEnables ; + + ------------------------------------------------------------ + procedure ReadLogEnables (FileName : string) is + ------------------------------------------------------------ + file AlertLogInitFile : text open READ_MODE is FileName ; + begin + ReadLogEnables(AlertLogInitFile) ; + end procedure ReadLogEnables ; + + ------------------------------------------------------------ + function PathTail (A : string) return string is + ------------------------------------------------------------ + alias aA : string(1 to A'length) is A ; + begin + for i in aA'length - 1 downto 1 loop + if aA(i) = ':' then + return aA(i+1 to aA'length-1) ; + end if ; + end loop ; + return aA ; + end function PathTail ; + + -- ------------------------------------------------------------ + -- Deprecated + -- + + ------------------------------------------------------------ + -- deprecated + procedure AlertIf( condition : boolean ; AlertLogID : AlertLogIDType ; Message : string ; Level : AlertType := ERROR ) is + begin + AlertIf( AlertLogID, condition, Message, Level) ; + end procedure AlertIf ; + + ------------------------------------------------------------ + -- deprecated + impure function AlertIf( condition : boolean ; AlertLogID : AlertLogIDType ; Message : string ; Level : AlertType := ERROR ) return boolean is + begin + return AlertIf( AlertLogID, condition, Message, Level) ; + end function AlertIf ; + + ------------------------------------------------------------ + -- deprecated + procedure AlertIfNot( condition : boolean ; AlertLogID : AlertLogIDType ; Message : string ; Level : AlertType := ERROR ) is + begin + AlertIfNot( AlertLogID, condition, Message, Level) ; + end procedure AlertIfNot ; + + ------------------------------------------------------------ + -- deprecated + impure function AlertIfNot( condition : boolean ; AlertLogID : AlertLogIDType ; Message : string ; Level : AlertType := ERROR ) return boolean is + begin + return AlertIfNot( AlertLogID, condition, Message, Level) ; + end function AlertIfNot ; + + ------------------------------------------------------------ + -- deprecated + procedure AffirmIf( + AlertLogID : AlertLogIDType ; + condition : boolean ; + Message : string ; + LogLevel : LogType ; -- := PASSED + AlertLevel : AlertType := ERROR + ) is + begin + AlertLogStruct.IncAffirmCount ; -- increment check count + if condition then + -- passed + AlertLogStruct.Log(AlertLogID, Message, LogLevel) ; -- call log +-- AlertLogStruct.IncAffirmPassCount ; -- increment pass & check count + else + AlertLogStruct.Alert(AlertLogID, Message, AlertLevel) ; -- signal failure + end if ; + end procedure AffirmIf ; + + ------------------------------------------------------------ + -- deprecated + procedure AffirmIf( AlertLogID : AlertLogIDType ; condition : boolean ; Message : string ; AlertLevel : AlertType ) is + begin + AffirmIf(AlertLogID, condition, Message, PASSED, AlertLevel) ; + end procedure AffirmIf ; + + ------------------------------------------------------------ + -- deprecated + procedure AffirmIf(condition : boolean ; Message : string ; LogLevel : LogType ; AlertLevel : AlertType := ERROR) is + begin + AffirmIf(ALERT_DEFAULT_ID, condition, Message, LogLevel, AlertLevel) ; + end procedure AffirmIf; + + ------------------------------------------------------------ + -- deprecated + procedure AffirmIf(condition : boolean ; Message : string ; AlertLevel : AlertType ) is + begin + AffirmIf(ALERT_DEFAULT_ID, condition, Message, PASSED, AlertLevel) ; + end procedure AffirmIf; + +end package body AlertLogPkg ; \ No newline at end of file diff --git a/test/OSVVM/CoveragePkg.vhd b/OSVVM/CoveragePkg.vhd old mode 100755 new mode 100644 similarity index 68% rename from test/OSVVM/CoveragePkg.vhd rename to OSVVM/CoveragePkg.vhd index f54dbd0..2fee28e --- a/test/OSVVM/CoveragePkg.vhd +++ b/OSVVM/CoveragePkg.vhd @@ -1,19 +1,20 @@ -- -- File Name: CoveragePkg.vhd -- Design Unit Name: CoveragePkg --- Revision: STANDARD VERSION, revision 2014.01 +-- Revision: STANDARD VERSION -- -- Maintainer: Jim Lewis email: jim@synthworks.com -- Contributor(s): -- Jim Lewis SynthWorks -- Matthias Alles Creonic. Inspired GetMinBinVal, GetMinPoint, GetCov -- Jerry Kaczynski Aldec. Inspired GetBin function --- +-- Sebastian Dunst Inspired GetBinName function +-- ... Aldec Worked on VendorCov functional coverage interface -- -- Package Defines -- Functional coverage modeling utilities and data structure -- --- Developed for: +-- Developed by/for: -- SynthWorks Design Inc. -- VHDL Training Classes -- 11898 SW 128th Ave. Tigard, Or 97223 @@ -22,80 +23,32 @@ -- Latest standard version available at: -- http://www.SynthWorks.com/downloads -- --- Revision History: See also CoveragePkg_release_notes.pdf +-- Revision History: For more details, see CoveragePkg_release_notes.pdf -- Date Version Description -- 06/2010: 0.1 Initial revision -- 09/2010 Release in SynthWorks' VHDL Testbenches and Verification classes --- 02/2011: 1.0 Requires VHDL-2008 types integer_vector and boolean_vecctor --- Changed CoverBinType to facilitage long term support of cross coverage +-- 02/2011: 1.0 Changed CoverBinType to facilitage long term support of cross coverage -- 02/2011: 1.1 Added GetMinCov, GetMaxCov, CountCovHoles, GetCovHole -- 04/2011: 2.0 Added protected type based data structure: CovPType -- 06/2011: 2.1 Removed signal based coverage modeling -- 07/2011: 2.2 Added randomization with coverage goals (AtLeast), weight, and percentage thresholds --- Revised RandCovPoint, RandCovBinVal, AddBins, AddCross, GenBin, Added SetWeightMode --- Randomization with weights/weight modes --- Cleaned up parameter naming --- 11/2011: 2.2a Changed constants ALL_RANGE, ZERO_BIN, and ONE_BIN to have a 1 index --- rather than 0 to match the range of BinVal +-- 11/2011: 2.2a Changed constants ALL_RANGE, ZERO_BIN, and ONE_BIN to have a 1 index -- 12/2011: 2.2b Fixed minor inconsistencies on interface declarations. --- Package RandomPkg is assumed to be in the same library as CoveragePkg --- 01/2012: 2.3 Added Function GetBin from Jerry K. --- Made write for RangeArrayType visible --- 01/2012: 2.4 --- Revised AddBins and AddCross to handle merging and deletion for overlapping bins --- Note merging is an experimental feature. --- Renamed RandCovHole to RandCovBinVal - maintained old version calls new --- Renamed GetCovHole to GetHoleBinVal - maintained old version calls new --- 04/2013: 2013.04 --- Revised AddBins and AddCross s.t. bin merging is off by default. --- Added SetMerging to enable/disable merging. --- Note: Merging is an experimental feature and still evolving. --- Revised AddBins and AddCross to check for changes in BinVal size (different size bin). --- Added RandCovPoint for integer. --- Added SetThresholding and SetCovThreshold(Percent) to enable/disable(default) thresholding. --- Revised RandCovPoint and RandCovBinVal to use new mechanism. --- Added SetCovTarget to increase/decrease coverage goals for longer/shorter simulation runs. --- Made CovTarget the default percentage goal (via overloading) for methods RandCovPoint, --- RandCovBinVal, IsCovered, CountCovHoles, GetHoleBinVal, and WriteCovHoles --- Revised SetIllegalMode and ICover to support ILLEGAL_FAILURE (severity FAILURE on illegal bin). --- Added manual bin iteration support. --- BinIndex: GetNumBins, GetMinIndex, GetMaxIndex --- BinVal: GetBinVal(BinIndex), GetMinBinVal, GetMaxBinVal --- Point: GetPoint (BinIndex), GetMinPoint, GetMaxPoint --- Added GetCov to return the current percent done of the entire coverage model. --- Added FileOpenWriteBin and FileCloseWriteBin to specify default file for WriteBin, WriteCovHoles, and DumpBin --- Added CompareBins to facilitate comparing two coverage models. --- Revised WriteBin, WriteCovHoles, and WriteCovDb to check for uninitialized model. --- Revised WriteBins and WriteCovHoles to only print weight if the selected WeightMode uses the weight. --- Added IsInitialized to check if a coverage model is initialized. --- Added GetBinInfo and GetBinValLength to get bin information --- Changed WriteCovDb default for File_Open_Kind to WRITE_MODE --- Revised WriteCovDb and ReadCovDb for new internal control/state variables --- Removed IgnoreBin with AtLeast and Weight parameters. These are zero for ignore bins. --- Revised method naming for consistency. The following have changed: --- New Name Old Name Why --- CovBinErrCnt GetErrorCount Consistency between packages --- GetMinCount GetMinCov[return integer] Naming clarity --- GetMaxCount GetMaxCov[return integer] Naming clarity --- SetName SetItemName SetName now does multi-line messages --- Deprecated usage of the AtLeast parameter (integer) with the following methods: --- RandCovPoint, RandCovBinVal, IsCovered, CountCovHoles, --- GetHoleBinVal, and WriteCovHoles. --- 5/2013 2013.05 --- No changes of substance. --- Removed extra variable declaration in functions GetHoleBinval, --- RandCovBinVal, RandCovHole, GetHoleBinVal --- Using work.RandomPkg.NULL_RANGE_TYPE to remove NULL range warnings --- 1/2014 2014.01 --- Revised ReadCovDb to support merging of coverage models --- Revised RandCovPoint and RandCovBinVal to log the bin index in the LastIndex variable --- Revised ICover to look in bin referenced by LastIndex first --- Added GetLastIndex and GetLastBinVal --- Revised AddBins and AddCross bin merging to allow arbitrary CountBin overlap (facilitated by LastIndex) --- Note: Merging is an experimental feature and still evolving. --- Split SetName into SetMessage (headers) and SetName (printing illegal bins) --- Added methods GetItemCount and GetTotalCovGoal --- Revised GetCov to use CovTarget and overloaded to use a PercentCov parameter. +-- 01/2012: 2.3 Added Function GetBin from Jerry K. Made write for RangeArrayType visible +-- 01/2012: 2.4 Added Merging of bins +-- 04/2013: 2013.04 Thresholding, CovTarget, Merging off by default, +-- 5/2013 2013.05 Release with updated RandomPkg. Minimal changes. +-- 1/2014 2014.01 Merging of Cov Models, LastIndex +-- 7/2014 2014.07 Bin Naming (for requirements tracking), WriteBin with Pass/Fail, GenBin[integer_vector] +-- 12/2014 2014.07a Fix memory leak in deallocate. Removed initialied pointers which can lead to leaks. +-- 01/2015 2015.01 Use AlertLogPkg to count assertions and filter log messages +-- 06/2015 2015.06 AddCross[CovMatrix?Type], Mirroring for WriteBin +-- 01/2016 2016.01 Fixes for pure functions. Added bounds checking on ICover +-- 03/2016 2016.03 Added GetBinName(Index) to retrieve a bin's name +-- 11/2016 2016.11 Added VendorCovApiPkg and calls to bind it in. +-- 05/2017 2017.05 Updated WriteBin name printing +-- ClearCov (deprecates SetCovZero) +-- -- -- Development Notes: -- The coverage procedures are named ICover to avoid conflicts with @@ -106,7 +59,7 @@ -- composites with unconstrained elements -- -- --- Copyright (c) 2010 - 2013 by SynthWorks Design Inc. All rights reserved. +-- Copyright (c) 2010 - 2017 by SynthWorks Design Inc. All rights reserved. -- -- Verbatim copies of this source file may be used and -- distributed without restriction. @@ -144,9 +97,15 @@ use std.textio.all ; -- library ieee_proposed ; -- remove with VHDL-2008 -- use ieee_proposed.standard_additions.all ; -- remove with VHDL-2008 +use work.TextUtilPkg.all ; +use work.TranscriptPkg.all ; +use work.AlertLogPkg.all ; use work.RandomBasePkg.all ; use work.RandomPkg.all ; -use work.MessagePkg.all ; +use work.NamePkg.all ; +use work.MessagePkg.all ; +use work.OsvvmGlobalPkg.all ; +use work.VendorCovApiPkg.all ; package CoveragePkg is @@ -169,11 +128,19 @@ package CoveragePkg is constant COV_IGNORE : integer := 0 ; constant COV_ILLEGAL : integer := -1 ; + -- type OsvvmOptionsType is (OPT_DEFAULT, FALSE, TRUE) ; + alias CovOptionsType is work.OsvvmGlobalPkg.OsvvmOptionsType ; + constant COV_OPT_INIT_PARM_DETECT : CovOptionsType := work.OsvvmGlobalPkg.OPT_INIT_PARM_DETECT ; + -- For backward compatibility. Don't add to other packages. + alias DISABLED is work.OsvvmGlobalPkg.DISABLED [return work.OsvvmGlobalPkg.OsvvmOptionsType ]; + alias ENABLED is work.OsvvmGlobalPkg.ENABLED [return work.OsvvmGlobalPkg.OsvvmOptionsType ]; + +-- Deprecated -- Used for easy manual entry. Order: min, max, action -- Intentionally did not use a record to allow other input -- formats in the future with VHDL-2008 unconstrained arrays -- of unconstrained elements - type CovBinManualType is array (natural range <>) of integer_vector(0 to 2) ; + -- type CovBinManualType is array (natural range <>) of integer_vector(0 to 2) ; type CovBinBaseType is record BinVal : RangeArrayType(1 to 1) ; @@ -270,7 +237,10 @@ package CoveragePkg is Weight : integer ; end record ; type CovMatrix9Type is array (natural range <>) of CovMatrix9BaseType ; - + + ------------------------------------------------------------ VendorCov + -- VendorCov Conversion for Vendor supported functional coverage modeling + function ToVendorCovBinVal (BinVal : RangeArrayType) return VendorCovRangeArrayType ; ------------------------------------------------------------ function ToMinPoint (A : RangeArrayType) return integer ; @@ -287,7 +257,6 @@ package CoveragePkg is variable result : out integer ) ; - ------------------------------------------------------------ procedure ToRandPoint( -- BinVal to Random Point @@ -306,12 +275,19 @@ package CoveragePkg is type CovPType is protected procedure FileOpenWriteBin (FileName : string; OpenKind : File_Open_Kind ) ; procedure FileCloseWriteBin ; + procedure SetAlertLogID (A : AlertLogIDType) ; + procedure SetAlertLogID(Name : string ; ParentID : AlertLogIDType := ALERTLOG_BASE_ID ; CreateHierarchy : Boolean := TRUE) ; + impure function GetAlertLogID return AlertLogIDType ; + -- procedure FileOpenWriteCovDb (FileName : string; OpenKind : File_Open_Kind ) ; -- procedure FileCloseWriteCovDb ; procedure SetIllegalMode (A : IllegalModeType) ; procedure SetWeightMode (A : WeightModeType; Scale : real := 1.0) ; - procedure SetName (NameIn : String) ; - procedure SetMessage (MessageIn : String) ; + procedure SetName (Name : String) ; + impure function SetName (Name : String) return string ; + impure function GetName return String ; + impure function GetCovModelName return String ; + procedure SetMessage (Message : String) ; procedure DeallocateName ; -- clear name procedure DeallocateMessage ; -- clear message procedure SetThresholding(A : boolean := TRUE ) ; -- 2.5 @@ -321,26 +297,61 @@ package CoveragePkg is procedure SetMerging(A : boolean := TRUE ) ; -- 2.5 procedure SetCountMode (A : CountModeType) ; procedure InitSeed (S : string ) ; + impure function InitSeed (S : string ) return string ; procedure InitSeed (I : integer ) ; procedure SetSeed (RandomSeedIn : RandomSeedType ) ; impure function GetSeed return RandomSeedType ; + ------------------------------------------------------------ + procedure SetReportOptions ( + WritePassFail : CovOptionsType := COV_OPT_INIT_PARM_DETECT ; + WriteBinInfo : CovOptionsType := COV_OPT_INIT_PARM_DETECT ; + WriteCount : CovOptionsType := COV_OPT_INIT_PARM_DETECT ; + WriteAnyIllegal : CovOptionsType := COV_OPT_INIT_PARM_DETECT ; + WritePrefix : string := OSVVM_STRING_INIT_PARM_DETECT ; + PassName : string := OSVVM_STRING_INIT_PARM_DETECT ; + FailName : string := OSVVM_STRING_INIT_PARM_DETECT + ) ; + procedure SetBinSize (NewNumBins : integer) ; ------------------------------------------------------------ procedure AddBins ( + ------------------------------------------------------------ + Name : String ; AtLeast : integer ; Weight : integer ; - CovBin : CovBinType + CovBin : CovBinType + ) ; + procedure AddBins ( Name : String ; AtLeast : integer ; CovBin : CovBinType ) ; + procedure AddBins ( Name : String ; CovBin : CovBinType) ; + procedure AddBins ( AtLeast : integer ; Weight : integer ; CovBin : CovBinType ) ; + procedure AddBins ( AtLeast : integer ; CovBin : CovBinType ) ; + procedure AddBins ( CovBin : CovBinType ) ; + + ------------------------------------------------------------ + procedure AddCross( + ------------------------------------------------------------ + Name : string ; + AtLeast : integer ; + Weight : integer ; + Bin1, Bin2 : CovBinType ; + Bin3, Bin4, Bin5, Bin6, Bin7, Bin8, Bin9, Bin10, Bin11, Bin12, Bin13, + Bin14, Bin15, Bin16, Bin17, Bin18, Bin19, Bin20 : CovBinType := NULL_BIN ) ; - procedure AddBins (AtLeast : integer ; CovBin : CovBinType) ; - procedure AddBins (CovBin : CovBinType) ; + ------------------------------------------------------------ + procedure AddCross( + Name : string ; + AtLeast : integer ; + Bin1, Bin2 : CovBinType ; + Bin3, Bin4, Bin5, Bin6, Bin7, Bin8, Bin9, Bin10, Bin11, Bin12, Bin13, + Bin14, Bin15, Bin16, Bin17, Bin18, Bin19, Bin20 : CovBinType := NULL_BIN + ) ; ------------------------------------------------------------ procedure AddCross( - AtLeast : integer ; - Weight : integer ; + Name : string ; Bin1, Bin2 : CovBinType ; Bin3, Bin4, Bin5, Bin6, Bin7, Bin8, Bin9, Bin10, Bin11, Bin12, Bin13, Bin14, Bin15, Bin16, Bin17, Bin18, Bin19, Bin20 : CovBinType := NULL_BIN @@ -348,7 +359,16 @@ package CoveragePkg is ------------------------------------------------------------ procedure AddCross( - AtLeast : integer ; + AtLeast : integer ; + Weight : integer ; + Bin1, Bin2 : CovBinType ; + Bin3, Bin4, Bin5, Bin6, Bin7, Bin8, Bin9, Bin10, Bin11, Bin12, Bin13, + Bin14, Bin15, Bin16, Bin17, Bin18, Bin19, Bin20 : CovBinType := NULL_BIN + ) ; + + ------------------------------------------------------------ + procedure AddCross( + AtLeast : integer ; Bin1, Bin2 : CovBinType ; Bin3, Bin4, Bin5, Bin6, Bin7, Bin8, Bin9, Bin10, Bin11, Bin12, Bin13, Bin14, Bin15, Bin16, Bin17, Bin18, Bin19, Bin20 : CovBinType := NULL_BIN @@ -361,12 +381,14 @@ package CoveragePkg is Bin14, Bin15, Bin16, Bin17, Bin18, Bin19, Bin20 : CovBinType := NULL_BIN ) ; + procedure Deallocate ; procedure ICoverLast ; procedure ICover( CovPoint : integer) ; procedure ICover( CovPoint : integer_vector) ; + procedure ClearCov ; procedure SetCovZero ; impure function IsInitialized return boolean ; @@ -383,10 +405,10 @@ package CoveragePkg is impure function IsCovered ( PercentCov : real ) return boolean ; impure function GetCov ( PercentCov : real ) return real ; impure function GetCov return real ; -- PercentCov of entire model/all bins - impure function GetItemCount return integer ; - impure function GetTotalCovGoal ( PercentCov : real ) return integer ; - impure function GetTotalCovGoal return integer ; - impure function GetLastIndex return integer ; + impure function GetItemCount return integer ; + impure function GetTotalCovGoal ( PercentCov : real ) return integer ; + impure function GetTotalCovGoal return integer ; + impure function GetLastIndex return integer ; -- Return BinVal impure function GetBinVal ( BinIndex : integer ) return RangeArrayType ; @@ -426,31 +448,82 @@ package CoveragePkg is impure function GetBin ( BinIndex : integer ) return CovMatrix7BaseType ; impure function GetBin ( BinIndex : integer ) return CovMatrix8BaseType ; impure function GetBin ( BinIndex : integer ) return CovMatrix9BaseType ; + impure function GetBinName ( BinIndex : integer; DefaultName : string := "" ) return string ; + + ------------------------------------------------------------ + procedure WriteBin ( + WritePassFail : CovOptionsType := COV_OPT_INIT_PARM_DETECT ; + WriteBinInfo : CovOptionsType := COV_OPT_INIT_PARM_DETECT ; + WriteCount : CovOptionsType := COV_OPT_INIT_PARM_DETECT ; + WriteAnyIllegal : CovOptionsType := COV_OPT_INIT_PARM_DETECT ; + WritePrefix : string := OSVVM_STRING_INIT_PARM_DETECT ; + PassName : string := OSVVM_STRING_INIT_PARM_DETECT ; + FailName : string := OSVVM_STRING_INIT_PARM_DETECT + ) ; + + ------------------------------------------------------------ + procedure WriteBin ( -- With LogLevel + LogLevel : LogType ; + WritePassFail : CovOptionsType := COV_OPT_INIT_PARM_DETECT ; + WriteBinInfo : CovOptionsType := COV_OPT_INIT_PARM_DETECT ; + WriteCount : CovOptionsType := COV_OPT_INIT_PARM_DETECT ; + WriteAnyIllegal : CovOptionsType := COV_OPT_INIT_PARM_DETECT ; + WritePrefix : string := OSVVM_STRING_INIT_PARM_DETECT ; + PassName : string := OSVVM_STRING_INIT_PARM_DETECT ; + FailName : string := OSVVM_STRING_INIT_PARM_DETECT + ) ; + + ------------------------------------------------------------ + procedure WriteBin ( + FileName : string; + OpenKind : File_Open_Kind := APPEND_MODE ; + WritePassFail : CovOptionsType := COV_OPT_INIT_PARM_DETECT ; + WriteBinInfo : CovOptionsType := COV_OPT_INIT_PARM_DETECT ; + WriteCount : CovOptionsType := COV_OPT_INIT_PARM_DETECT ; + WriteAnyIllegal : CovOptionsType := COV_OPT_INIT_PARM_DETECT ; + WritePrefix : string := OSVVM_STRING_INIT_PARM_DETECT ; + PassName : string := OSVVM_STRING_INIT_PARM_DETECT ; + FailName : string := OSVVM_STRING_INIT_PARM_DETECT + ) ; - -- procedure WriteBin ( file f : text ) ; - procedure WriteBin ; - procedure WriteBin ( FileName : string; OpenKind : File_Open_Kind := APPEND_MODE ) ; - procedure WriteCovHoles ; + ------------------------------------------------------------ + procedure WriteBin ( -- With LogLevel + LogLevel : LogType ; + FileName : string; + OpenKind : File_Open_Kind := APPEND_MODE ; + WritePassFail : CovOptionsType := COV_OPT_INIT_PARM_DETECT ; + WriteBinInfo : CovOptionsType := COV_OPT_INIT_PARM_DETECT ; + WriteCount : CovOptionsType := COV_OPT_INIT_PARM_DETECT ; + WriteAnyIllegal : CovOptionsType := COV_OPT_INIT_PARM_DETECT ; + WritePrefix : string := OSVVM_STRING_INIT_PARM_DETECT ; + PassName : string := OSVVM_STRING_INIT_PARM_DETECT ; + FailName : string := OSVVM_STRING_INIT_PARM_DETECT + ) ; + + procedure WriteCovHoles ( LogLevel : LogType := ALWAYS ) ; procedure WriteCovHoles ( PercentCov : real ) ; + procedure WriteCovHoles ( LogLevel : LogType ; PercentCov : real ) ; procedure WriteCovHoles ( FileName : string; OpenKind : File_Open_Kind := APPEND_MODE ) ; + procedure WriteCovHoles ( LogLevel : LogType ; FileName : string; OpenKind : File_Open_Kind := APPEND_MODE ) ; procedure WriteCovHoles ( FileName : string; PercentCov : real ; OpenKind : File_Open_Kind := APPEND_MODE ) ; - procedure DumpBin ; -- Development only + procedure WriteCovHoles ( LogLevel : LogType ; FileName : string; PercentCov : real ; OpenKind : File_Open_Kind := APPEND_MODE ) ; + procedure DumpBin (LogLevel : LogType := DEBUG) ; -- Development only - procedure ReadCovDb (FileName : string; Merge : boolean := FALSE) ; + procedure ReadCovDb (FileName : string; Merge : boolean := FALSE) ; procedure WriteCovDb (FileName : string; OpenKind : File_Open_Kind := WRITE_MODE ) ; impure function GetErrorCount return integer ; -- These support usage of cross coverage constants -- Also support the older AddBins(GenCross(...)) methodology -- which has been replaced by AddCross - procedure AddBins (CovBin : CovMatrix2Type) ; - procedure AddBins (CovBin : CovMatrix3Type) ; - procedure AddBins (CovBin : CovMatrix4Type) ; - procedure AddBins (CovBin : CovMatrix5Type) ; - procedure AddBins (CovBin : CovMatrix6Type) ; - procedure AddBins (CovBin : CovMatrix7Type) ; - procedure AddBins (CovBin : CovMatrix8Type) ; - procedure AddBins (CovBin : CovMatrix9Type) ; + procedure AddCross (CovBin : CovMatrix2Type ; Name : String := "") ; + procedure AddCross (CovBin : CovMatrix3Type ; Name : String := "") ; + procedure AddCross (CovBin : CovMatrix4Type ; Name : String := "") ; + procedure AddCross (CovBin : CovMatrix5Type ; Name : String := "") ; + procedure AddCross (CovBin : CovMatrix6Type ; Name : String := "") ; + procedure AddCross (CovBin : CovMatrix7Type ; Name : String := "") ; + procedure AddCross (CovBin : CovMatrix8Type ; Name : String := "") ; + procedure AddCross (CovBin : CovMatrix9Type ; Name : String := "") ; ------------------------------------------------------------ -- Remaining are Deprecated @@ -488,9 +561,21 @@ package CoveragePkg is impure function GetCovHole ( ReqHoleNum : integer ; AtLeast : integer ) return RangeArrayType ; procedure WriteCovHoles ( AtLeast : integer ) ; + procedure WriteCovHoles ( LogLevel : LogType ; AtLeast : integer ) ; procedure WriteCovHoles ( FileName : string; AtLeast : integer ; OpenKind : File_Open_Kind := APPEND_MODE ) ; - - end protected CovPType ; + procedure WriteCovHoles ( LogLevel : LogType ; FileName : string; AtLeast : integer ; OpenKind : File_Open_Kind := APPEND_MODE ) ; + + -- Replaced by a more appropriately named AddCross + procedure AddBins (CovBin : CovMatrix2Type ; Name : String := "") ; + procedure AddBins (CovBin : CovMatrix3Type ; Name : String := "") ; + procedure AddBins (CovBin : CovMatrix4Type ; Name : String := "") ; + procedure AddBins (CovBin : CovMatrix5Type ; Name : String := "") ; + procedure AddBins (CovBin : CovMatrix6Type ; Name : String := "") ; + procedure AddBins (CovBin : CovMatrix7Type ; Name : String := "") ; + procedure AddBins (CovBin : CovMatrix8Type ; Name : String := "") ; + procedure AddBins (CovBin : CovMatrix9Type ; Name : String := "") ; + + end protected CovPType ; ------------------------------------------------------------------------------------------ -- XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX CovPType XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -- XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX CovPType XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX @@ -506,6 +591,13 @@ package CoveragePkg is variable ErrorCount : inout integer ) ; + ------------------------------------------------------------ + -- Experimental. Intended primarily for development. + procedure CompareBins ( + ------------------------------------------------------------ + variable Bin1 : inout CovPType ; + variable Bin2 : inout CovPType + ) ; -- -- Support for AddBins and AddCross @@ -526,6 +618,17 @@ package CoveragePkg is function GenBin(Min, Max : integer) return CovBinType ; function GenBin(A : integer) return CovBinType ; + ------------------------------------------------------------ + function GenBin( + ------------------------------------------------------------ + AtLeast : integer ; + Weight : integer ; + A : integer_vector + ) return CovBinType ; + + function GenBin ( AtLeast : integer ; A : integer_vector ) return CovBinType ; + function GenBin ( A : integer_vector ) return CovBinType ; + ------------------------------------------------------------ function IllegalBin ( Min, Max, NumBin : integer ) return CovBinType ; @@ -535,33 +638,15 @@ package CoveragePkg is function IllegalBin ( Min, Max : integer ) return CovBinType ; function IllegalBin ( A : integer ) return CovBinType ; - - ---------------------------------------------------------- - -- function IgnoreBin ( - ---------------------------------------------------------- - -- AtLeast : integer ; - -- Weight : integer ; - -- Min, Max : integer ; - -- NumBin : integer - -- ) return CovBinType ; - -- function IgnoreBin (AtLeast : integer ; Min, Max, NumBin : integer) return CovBinType ; - - -- All items in range in a single CovBin + +-- IgnoreBin should never have an AtLeast parameter ------------------------------------------------------------ function IgnoreBin (Min, Max, NumBin : integer) return CovBinType ; ------------------------------------------------------------ - function IgnoreBin (Min, Max : integer) return CovBinType ; + function IgnoreBin (Min, Max : integer) return CovBinType ; -- All items in range in a single CovBin function IgnoreBin (A : integer) return CovBinType ; - ------------------------------------------------------------ - function GenBin ( - -- Manual entry format for CovBin within lots of extra parens - ------------------------------------------------------------ - ManualBin : CovBinManualType - ) return CovBinType ; - - -- With VHDL-2008, there will be one GenCross that returns CovBinType -- and has inputs initialized to NULL_BIN - see AddCross ------------------------------------------------------------ @@ -663,38 +748,32 @@ package CoveragePkg is function GenCross( Bin1, Bin2, Bin3, Bin4, Bin5, Bin6, Bin7, Bin8, Bin9 : CovBinType ) return CovMatrix9Type ; - ------------------------------------------------------------ - procedure increment( signal Count : inout integer ) ; - procedure increment( signal Count : inout integer ; enable : boolean ) ; - procedure increment( signal Count : inout integer ; enable : std_ulogic ) ; - - ------------------------------------------------------------ -- Utilities. Remove if added to std.standard function to_integer ( B : boolean ) return integer ; function to_integer ( SL : std_logic ) return integer ; function to_integer_vector ( BV : boolean_vector ) return integer_vector ; function to_integer_vector ( SLV : std_logic_vector ) return integer_vector ; + + + ------------------------------------------------------------ + ------------------------------------------------------------ +-- Deprecated: These are not part of the coverage model + + procedure increment( signal Count : inout integer ) ; + procedure increment( signal Count : inout integer ; enable : boolean ) ; + procedure increment( signal Count : inout integer ; enable : std_ulogic ) ; -end package CoveragePkg ; ---- ////////////////////////////////////////////////////////////////////////////////////////////// ---- ////////////////////////////////////////////////////////////////////////////////////////////// -package body CoveragePkg is - ------------------------------------------------------------ - function inside ( - -- package local - ------------------------------------------------------------ - CovPoint : integer ; - BinVal : RangeType - ) return boolean is - begin - return CovPoint >= BinVal.min and CovPoint <= BinVal.max ; - end function inside ; +end package CoveragePkg ; +--- /////////////////////////////////////////////////////////////////////////// +--- /////////////////////////////////////////////////////////////////////////// +--- /////////////////////////////////////////////////////////////////////////// +package body CoveragePkg is ------------------------------------------------------------ function inside ( -- package local @@ -733,9 +812,9 @@ package body CoveragePkg is ------------------------------------------------------------ - procedure write ( + procedure write ( variable buf : inout line ; - CovPoint : integer_vector + CovPoint : integer_vector ) is -- package local. called by ICover ------------------------------------------------------------ @@ -748,7 +827,6 @@ package body CoveragePkg is swrite(buf, ")") ; end procedure write ; - ------------------------------------------------------------ procedure write ( file f : text ; BinVal : RangeArrayType ) is -- called by WriteBin and WriteCovHoles @@ -766,7 +844,6 @@ package body CoveragePkg is end loop ; end procedure write ; - ------------------------------------------------------------ procedure write ( -- called by WriteBin and WriteCovHoles @@ -805,60 +882,6 @@ package body CoveragePkg is end loop ; end procedure WriteBinVal ; - - ------------------------------------------------------------ - -- package local - function failed (InValid : boolean ; Message : string := " ") return boolean is - -- Move to TextUtilPkg and make visible? - ------------------------------------------------------------ - begin - if InValid then - report Message severity failure ; - end if ; - return InValid ; - end function failed ; - - - ------------------------------------------------------------ - -- package local - procedure EmptyOrCommentLine ( - -- Better as Function, but not supported in VHDL functions - ------------------------------------------------------------ - variable L : InOut line ; - variable Empty : out boolean - ) is - variable Valid : boolean ; - variable Char : character ; - constant NBSP : CHARACTER := CHARACTER'val(160); -- space character - begin - Empty := TRUE ; - - -- if line empty (null or 0 length), Empty = TRUE - if L = null or L.all'length = 0 then - return ; - end if ; - - -- if line starts with '#', empty = TRUE - if L.all(1) = '#' then - return ; - end if ; - - -- if line starts with '--', empty = TRUE - if L.all'length >= 2 and L.all(1) = '-' and L.all(2) = '-' then - return ; - end if ; - - -- Otherwise, remove white space and check for end of line - -- Code borrowed from David Bishop, skip_whitespace - WhiteSpLoop : while L /= null and L.all'length > 0 loop - if (L.all(1) = ' ' or L.all(1) = NBSP or L.all(1) = HT) then - read (L, Char, Valid) ; - else - Empty := FALSE ; - exit WhiteSpLoop ; - end if ; - end loop WhiteSpLoop ; - end procedure EmptyOrCommentLine ; ------------------------------------------------------------ -- package local for now @@ -881,7 +904,6 @@ package body CoveragePkg is end procedure read ; - -- ------------------------------------------------------------ function BinLengths ( -- package local, used by AddCross, GenCross @@ -961,7 +983,7 @@ package body CoveragePkg is -- ------------------------------------------------------------ function ConcatenateBins ( - -- package local, used by AddCross + -- package local, used by AddCross and GenCross -- ------------------------------------------------------------ BinIndex : integer_vector ; Bin1, Bin2, Bin3, Bin4, Bin5, Bin6, Bin7, Bin8, Bin9, Bin10, Bin11, @@ -1012,7 +1034,10 @@ package body CoveragePkg is when 18 => result(i) := aBin18(aBinIndex(i)) ; when 19 => result(i) := aBin19(aBinIndex(i)) ; when 20 => result(i) := aBin20(aBinIndex(i)) ; - when others => report "ConcatenateBins: More than 20 bins not supported" severity failure ; + when others => + -- pure functions cannot use alert and/or print + report "CoveragePkg.AddCross: More than 20 bins not supported" + severity FAILURE ; end case ; end loop ; return result ; @@ -1095,7 +1120,21 @@ package body CoveragePkg is return result ; end function MergeWeight ; + + ------------------------------------------------------------ VendorCov + -- VendorCov Conversion for Vendor supported functional coverage modeling + function ToVendorCovBinVal (BinVal : RangeArrayType) return VendorCovRangeArrayType is + ------------------------------------------------------------ + variable VendorCovBinVal : VendorCovRangeArrayType(BinVal'range); + begin -- VendorCov + for ArrIdx in BinVal'LEFT to BinVal'RIGHT loop -- VendorCov + VendorCovBinVal(ArrIdx) := (min => BinVal(ArrIdx).min, -- VendorCov + max => BinVal(ArrIdx).max) ; -- VendorCov + end loop; -- VendorCov + return VendorCovBinVal ; + end function ToVendorCovBinVal ; + ------------------------------------------------------------ function ToMinPoint (A : RangeArrayType) return integer is -- Used in testing @@ -1145,6 +1184,31 @@ package body CoveragePkg is result := VectorVal ; end procedure ToRandPoint ; + ------------------------------------------------------------ + -- Local. Get first word from a string + function GetWord (Message : string) return string is + ------------------------------------------------------------ + alias aMessage : string( 1 to Message'length) is Message ; + begin + for i in aMessage'range loop + if aMessage(i) = ' ' or aMessage(i) = HT then + return aMessage(1 to i-1) ; + end if ; + end loop ; + return aMessage ; + end function GetWord ; + + ------------------------------------------------------------ + -- Local -- long term move to MessagePkg? Used by WriteCovDb + procedure WriteMessage ( file f : text ; variable Message : inout MessagePType ) is + ------------------------------------------------------------ + variable buf : line ; + begin + for i in 1 to Message.GetCount loop + write(buf, string'(Message.Get(i))) ; + writeline(f, buf) ; + end loop ; + end procedure WriteMessage ; ------------------------------------------------------------------------------------------ -- XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX CovPType XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX @@ -1154,8 +1218,12 @@ package body CoveragePkg is type CovPType is protected body -- Name Data Structure - variable Message : MessagePType ; + variable CovNameVar : NamePType ; + variable CovMessageVar : MessagePType ; + -- Handle into Vendor Data Structure -- VendorCov + variable VendorCovHandleVar : VendorCovHandleType := 0 ; -- VendorCov + -- CoverageBin Data Structures type RangeArrayPtrType is access RangeArrayType ; @@ -1167,6 +1235,7 @@ package body CoveragePkg is Weight : integer ; PercentCov : real ; OrderCount : integer ; + Name : line ; end record CovBinBaseTempType ; type CovBinTempType is array (natural range <>) of CovBinBaseTempType ; type CovBinPtrType is access CovBinTempType ; @@ -1180,6 +1249,7 @@ package body CoveragePkg is -- Internal Modes and Names variable IllegalMode : IllegalModeType := ILLEGAL_ON ; + variable IllegalModeLevel : AlertType := ERROR ; variable WeightMode : WeightModeType := AT_LEAST ; variable WeightScale : real := 1.0 ; @@ -1194,12 +1264,23 @@ package body CoveragePkg is variable RV : RandomPType ; variable RvSeedInit : boolean := FALSE ; - file WriteBinFile : text ; variable WriteBinFileInit : boolean := FALSE ; + variable UsingLocalFile : boolean := FALSE ; + variable AlertLogIDVar : AlertLogIDType := OSVVM_ALERTLOG_ID ; + -- file WriteCovDbFile : text ; -- variable WriteCovDbFileInit : boolean := FALSE ; + -- Local WriteBin and WriteCovHoles formatting settings, defaults determined by CoverageGlobals + variable WritePassFailVar : CovOptionsType := COV_OPT_INIT_PARM_DETECT ; + variable WriteBinInfoVar : CovOptionsType := COV_OPT_INIT_PARM_DETECT ; + variable WriteCountVar : CovOptionsType := COV_OPT_INIT_PARM_DETECT ; + variable WriteAnyIllegalVar : CovOptionsType := COV_OPT_INIT_PARM_DETECT ; + variable WritePrefixVar : NamePType ; + variable PassNameVar : NamePType ; + variable FailNameVar : NamePType ; + ------------------------------------------------------------ procedure FileOpenWriteBin (FileName : string; OpenKind : File_Open_Kind ) is @@ -1209,7 +1290,6 @@ package body CoveragePkg is file_open( WriteBinFile , FileName , OpenKind ); end procedure FileOpenWriteBin ; - ------------------------------------------------------------ procedure FileCloseWriteBin is ------------------------------------------------------------ @@ -1218,9 +1298,34 @@ package body CoveragePkg is file_close( WriteBinFile) ; end procedure FileCloseWriteBin ; - + ------------------------------------------------------------ + procedure SetAlertLogID (A : AlertLogIDType) is + ------------------------------------------------------------ + begin + AlertLogIDVar := A ; + end procedure SetAlertLogID ; + + ------------------------------------------------------------ + procedure SetAlertLogID(Name : string ; ParentID : AlertLogIDType := ALERTLOG_BASE_ID ; CreateHierarchy : Boolean := TRUE) is + ------------------------------------------------------------ + begin + AlertLogIDVar := GetAlertLogID(Name, ParentID, CreateHierarchy) ; + if not RvSeedInit then -- Init seed if not initialized + RV.InitSeed(Name) ; + RvSeedInit := TRUE ; + end if ; + end procedure SetAlertLogID ; + + ------------------------------------------------------------ + impure function GetAlertLogID return AlertLogIDType is + ------------------------------------------------------------ + begin + return AlertLogIDVar ; + end function GetAlertLogID ; + + -- ------------------------------------------------------------ --- procedure FileOpenWriteCovDb (FileName : string; OpenKind : File_Open_Kind ) is +-- procedure FileOpen (FileName : string; OpenKind : File_Open_Kind ) is -- ------------------------------------------------------------ -- begin -- WriteCovDbFileInit := TRUE ; @@ -1235,78 +1340,150 @@ package body CoveragePkg is -- file_close( WriteCovDbFile ); -- end procedure FileCloseWriteCovDb ; + ------------------------------------------------------------ + procedure SetName (Name : String) is + ------------------------------------------------------------ + begin + CovNameVar.Set(Name) ; + -- Update if name updated after model created -- VendorCov + if IsInitialized then -- VendorCov + VendorCovSetName(VendorCovHandleVar, Name) ; -- VendorCov + end if ; -- VendorCov + if not RvSeedInit then -- Init seed if not initialized + RV.InitSeed(Name) ; + RvSeedInit := TRUE ; + end if ; + end procedure SetName ; + + ------------------------------------------------------------ + impure function SetName (Name : String) return string is + ------------------------------------------------------------ + begin + SetName(Name) ; -- call procedure above + return Name ; + end function SetName ; + + ------------------------------------------------------------ + impure function GetName return String is + ------------------------------------------------------------ + begin + return CovNameVar.Get("") ; + end function GetName ; + + ------------------------------------------------------------ + impure function GetCovModelName return String is + ------------------------------------------------------------ + begin + if CovNameVar.IsSet then + -- return Name if set + return CovNameVar.Get ; + elsif AlertLogIDVar /= OSVVM_ALERTLOG_ID then + -- otherwise return AlertLogName if it is set + return GetAlertLogName(AlertLogIDVar) ; + elsif CovMessageVar.IsSet then + -- otherwise Get the first word of the Message if it is set + return GetWord(string'(CovMessageVar.Get(1))) ; + else + return "" ; + end if ; + end function GetCovModelName ; + + ------------------------------------------------------------ + impure function GetNamePlus(prefix, suffix : string) return String is + ------------------------------------------------------------ + begin + if CovNameVar.IsSet then + -- return Name if set + return prefix & CovNameVar.Get & suffix ; + elsif AlertLogIDVar = OSVVM_ALERTLOG_ID and CovMessageVar.IsSet then + -- If AlertLogID not set, then use Message + return prefix & GetWord(string'(CovMessageVar.Get(1))) & suffix ; + else + return "" ; + end if ; + end function GetNamePlus ; + + ------------------------------------------------------------ + procedure SetMessage (Message : String) is + ------------------------------------------------------------ + begin + CovMessageVar.Set(Message) ; + -- VendorCov update if name updated after model created + if IsInitialized then -- VendorCov + -- Refine this? If CovNameVar or AlertLogIDName is set, -- VendorCov + -- it may be set to the same name again. -- VendorCov + VendorCovSetName(VendorCovHandleVar, GetCovModelName) ; -- VendorCov + end if ; -- VendorCov + if not RvSeedInit then -- Init seed if not initialized + RV.InitSeed(Message) ; + RvSeedInit := TRUE ; + end if ; + end procedure SetMessage ; + ------------------------------------------------------------ procedure SetIllegalMode (A : IllegalModeType) is ------------------------------------------------------------ begin IllegalMode := A ; + if IllegalMode = ILLEGAL_FAILURE then + IllegalModeLevel := FAILURE ; + else + IllegalModeLevel := ERROR ; + end if ; end procedure SetIllegalMode ; ------------------------------------------------------------ procedure SetWeightMode (A : WeightModeType; Scale : real := 1.0) is ------------------------------------------------------------ - variable buf : line ; + variable buf : line ; begin WeightMode := A ; WeightScale := Scale ; if (WeightMode = REMAIN_EXP) and (WeightScale > 2.0) then - swrite(buf, "%%WARNING: WeightScale > 2.0 and large Counts can cause RandCovPoint to fail due to integer values out of range") ; - writeline(OUTPUT, buf) ; + Alert(AlertLogIDVar, GetNamePlus(prefix => "in ", suffix => ", ") & "CoveragePkg.SetWeightMode:" & + " WeightScale > 2.0 and large Counts can cause RandCovPoint to fail due to integer values out of range", WARNING) ; end if ; if (WeightScale < 1.0) and (WeightMode = REMAIN_WEIGHT or WeightMode = REMAIN_SCALED) then - report "WeightScale must be > 1.0 when WeightMode = REMAIN_WEIGHT or WeightMode = REMAIN_SCALED" - severity failure ; + Alert(AlertLogIDVar, GetNamePlus(prefix => "in ", suffix => ", ") & "CoveragePkg.SetWeightMode:" & + " WeightScale must be > 1.0 when WeightMode = REMAIN_WEIGHT or WeightMode = REMAIN_SCALED", FAILURE) ; WeightScale := 1.0 ; end if; if WeightScale <= 0.0 then - report "WeightScale must be > 0.0" severity failure ; + Alert(AlertLogIDVar, GetNamePlus(prefix => "in ", suffix => ", ") & "CoveragePkg.SetWeightMode:" & + " WeightScale must be > 0.0", FAILURE) ; WeightScale := 1.0 ; end if; end procedure SetWeightMode ; - ------------------------------------------------------------ - procedure SetName (NameIn : String) is - ------------------------------------------------------------ - begin - Message.SetName(NameIn) ; - if not RvSeedInit then -- Init seed if not initialized - RV.InitSeed(NameIn) ; - RvSeedInit := TRUE ; - end if ; - end procedure SetName ; - - ------------------------------------------------------------ - procedure SetMessage (MessageIn : String) is - ------------------------------------------------------------ - begin - Message.SetMessage(MessageIn) ; - if not RvSeedInit then -- Init seed if not initialized - RV.InitSeed(MessageIn) ; - RvSeedInit := TRUE ; - end if ; - end procedure SetMessage ; - ------------------------------------------------------------ -- pt local for now -- file formal parameter not allowed with a public method - procedure WriteBinName ( file f : text ; S : string ; Prefix : string := "%%" ) is + procedure WriteBinName ( file f : text ; S : string ; Prefix : string := "%% " ) is ------------------------------------------------------------ variable MessageCount : integer ; - variable buf : line ; + variable MessageIndex : integer := 1 ; + variable buf : line ; begin - MessageCount := Message.GetMessageCount ; + MessageCount := CovMessageVar.GetCount ; if MessageCount = 0 then - if Prefix'length + S'length > 0 then - write(buf, Prefix & S) ; - writeline(f, buf) ; - -- write(f, Prefix & S & LF); - end if ; + write(buf, Prefix & S & GetCovModelName) ; -- Print name when no message + writeline(f, buf) ; else - write(buf, Prefix & S & Message.GetMessage(1)) ; - writeline(f, buf) ; - for i in 2 to MessageCount loop - write(buf, Prefix & Message.GetMessage(i)) ; - writeline(f, buf) ; + if CovNameVar.IsSet then + -- Print Name if set + write(buf, Prefix & S & CovNameVar.Get) ; + elsif AlertLogIDVar /= OSVVM_ALERTLOG_ID then + -- otherwise Print AlertLogName if it is set + write(buf, Prefix & S & string'(GetAlertLogName(AlertLogIDVar))) ; + else + -- otherwise print the first line of the message + MessageIndex := 2 ; + write(buf, Prefix & S & string'(CovMessageVar.Get(1))) ; + end if ; + writeline(f, buf) ; + for i in MessageIndex to MessageCount loop + write(buf, Prefix & string'(CovMessageVar.Get(i))) ; + writeline(f, buf) ; end loop ; end if ; end procedure WriteBinName ; @@ -1315,14 +1492,14 @@ package body CoveragePkg is procedure DeallocateMessage is ------------------------------------------------------------ begin - Message.DeallocateMessage ; + CovMessageVar.Deallocate ; end procedure DeallocateMessage ; ------------------------------------------------------------ procedure DeallocateName is ------------------------------------------------------------ begin - Message.DeallocateName ; + CovNameVar.Clear ; end procedure DeallocateName ; ------------------------------------------------------------ @@ -1341,7 +1518,8 @@ package body CoveragePkg is CovThreshold := Percent + 0.0001 ; -- used in less than else CovThreshold := 0.0001 ; -- used in less than - report "Invalid Threshold Value " & real'image(Percent) severity failure ; + Alert(AlertLogIDVar, GetNamePlus(prefix => "in ", suffix => ", ") & "CoveragePkg.SetCovThreshold:" & + " Invalid Threshold Value " & real'image(Percent), FAILURE) ; end if ; end procedure SetCovThreshold ; @@ -1381,6 +1559,15 @@ package body CoveragePkg is RvSeedInit := TRUE ; end procedure InitSeed ; + ------------------------------------------------------------ + impure function InitSeed (S : string ) return string is + ------------------------------------------------------------ + begin + RV.InitSeed(S) ; + RvSeedInit := TRUE ; + return S ; + end function InitSeed ; + ------------------------------------------------------------ procedure InitSeed (I : integer ) is ------------------------------------------------------------ @@ -1404,6 +1591,41 @@ package body CoveragePkg is return RV.GetSeed ; end function GetSeed ; + ------------------------------------------------------------ + procedure SetReportOptions ( + ------------------------------------------------------------ + WritePassFail : CovOptionsType := COV_OPT_INIT_PARM_DETECT ; + WriteBinInfo : CovOptionsType := COV_OPT_INIT_PARM_DETECT ; + WriteCount : CovOptionsType := COV_OPT_INIT_PARM_DETECT ; + WriteAnyIllegal : CovOptionsType := COV_OPT_INIT_PARM_DETECT ; + WritePrefix : string := OSVVM_STRING_INIT_PARM_DETECT ; + PassName : string := OSVVM_STRING_INIT_PARM_DETECT ; + FailName : string := OSVVM_STRING_INIT_PARM_DETECT + ) is + begin + if WritePassFail /= COV_OPT_INIT_PARM_DETECT then + WritePassFailVar := WritePassFail ; + end if ; + if WriteBinInfo /= COV_OPT_INIT_PARM_DETECT then + WriteBinInfoVar := WriteBinInfo ; + end if ; + if WriteCount /= COV_OPT_INIT_PARM_DETECT then + WriteCountVar := WriteCount ; + end if ; + if WriteAnyIllegal /= COV_OPT_INIT_PARM_DETECT then + WriteAnyIllegalVar := WriteAnyIllegal ; + end if ; + if WritePrefix /= OSVVM_STRING_INIT_PARM_DETECT then + WritePrefixVar.Set(WritePrefix) ; + end if ; + if PassName /= OSVVM_STRING_INIT_PARM_DETECT then + PassNameVar.Set(PassName) ; + end if ; + if FailName /= OSVVM_STRING_INIT_PARM_DETECT then + FailNameVar.Set(FailName) ; + end if ; + end procedure SetReportOptions ; + ------------------------------------------------------------ procedure SetBinSize (NewNumBins : integer) is @@ -1431,9 +1653,8 @@ package body CoveragePkg is if NumBins = 0 then BinValLength := CurBinValLength ; -- number of points in cross else - assert BinValLength = CurBinValLength - report Caller & ": Cross bins with different sizes prohibited" - severity failure ; + AlertIf(AlertLogIDVar, BinValLength /= CurBinValLength, GetNamePlus(prefix => "in ", suffix => ", ") & "CoveragePkg." & Caller & ":" & + " Cross coverage bins of different dimensions prohibited", FAILURE) ; end if; end procedure CheckBinValLength ; @@ -1490,37 +1711,47 @@ package body CoveragePkg is ------------------------------------------------------------ -- pt local - -- Inserts values into a new bin. - -- Called by InsertBin + -- Inserts values into a new bin. + -- Called by InsertBin procedure InsertNewBin( BinVal : RangeArrayType ; Action : integer ; Count : integer ; AtLeast : integer ; Weight : integer ; + Name : string ; PercentCov : real := 0.0 ) is begin + if (not IsInitialized) then -- VendorCov + if (BinVal'length > 1) then -- Cross Bin -- VendorCov + VendorCovHandleVar := VendorCovCrossCreate(GetCovModelName) ; -- VendorCov + else -- VendorCov + VendorCovHandleVar := VendorCovPointCreate(GetCovModelName); -- VendorCov + end if; -- VendorCov + end if; -- VendorCov + VendorCovBinAdd(VendorCovHandleVar, ToVendorCovBinVal(BinVal), Action, AtLeast, Name) ; -- VendorCov NumBins := NumBins + 1 ; CovBinPtr.all(NumBins).BinVal := new RangeArrayType'(BinVal) ; CovBinPtr.all(NumBins).Action := Action ; CovBinPtr.all(NumBins).Count := Count ; CovBinPtr.all(NumBins).AtLeast := AtLeast ; CovBinPtr.all(NumBins).Weight := Weight ; + CovBinPtr.all(NumBins).Name := new String'(Name) ; CovBinPtr.all(NumBins).PercentCov := PercentCov ; CovBinPtr.all(NumBins).OrderCount := 0 ; --- Metrics for evaluating randomization order Temp end procedure InsertNewBin ; - + ------------------------------------------------------------ -- pt local - -- Inserts values into a new bin. - -- Called by InsertBin + -- Inserts values into a new bin. + -- Called by InsertBin procedure MergeBin ( Position : Natural ; Count : integer ; AtLeast : integer ; - Weight : integer + Weight : integer ) is begin CovBinPtr.all(Position).Count := CovBinPtr.all(Position).Count + Count ; @@ -1530,7 +1761,7 @@ package body CoveragePkg is real(CovBinPtr.all(Position).Count)*100.0/maximum(real(CovBinPtr.all(Position).AtLeast), 1.0) ; end procedure MergeBin ; - + ------------------------------------------------------------ -- pt local -- All insertion comes here @@ -1545,65 +1776,70 @@ package body CoveragePkg is Count : integer ; AtLeast : integer ; Weight : integer ; + Name : string ; PercentCov : real := 0.0 ) is variable Position : integer ; variable FoundInside : boolean ; begin - if not MergingEnable then - InsertNewBin(BinVal, Action, Count, AtLeast, Weight, PercentCov) ; - + if not MergingEnable then + InsertNewBin(BinVal, Action, Count, AtLeast, Weight, Name, PercentCov) ; + else -- handle merging --- future optimization, FindBinInside only checks against Ignore and Illegal bins +-- future optimization, FindBinInside only checks against Ignore and Illegal bins FindBinInside(BinVal, Position, FoundInside) ; - - if not FoundInside then - InsertNewBin(BinVal, Action, Count, AtLeast, Weight, PercentCov) ; - + + if not FoundInside then + InsertNewBin(BinVal, Action, Count, AtLeast, Weight, Name, PercentCov) ; + elsif Action = COV_COUNT then -- when check only ignore and illegal bins, only action is to drop if CovBinPtr.all(Position).Action /= COV_COUNT then null ; -- drop count bin when it is inside a Illegal or Ignore bin - - elsif CovBinPtr.all(Position).BinVal.all = BinVal then - -- Bins match, so merge the count values - MergeBin (Position, Count, AtLeast, Weight) ; + + elsif CovBinPtr.all(Position).BinVal.all = BinVal and CovBinPtr.all(Position).Name.all = Name then + -- Bins match, so merge the count values + MergeBin (Position, Count, AtLeast, Weight) ; else -- Bins overlap, but do not match, insert new bin - InsertNewBin(BinVal, Action, Count, AtLeast, Weight, PercentCov) ; - end if; + InsertNewBin(BinVal, Action, Count, AtLeast, Weight, Name, PercentCov) ; + end if; elsif Action = COV_IGNORE then -- when check only ignore and illegal bins, only action is to report error if CovBinPtr.all(Position).Action = COV_COUNT then - InsertNewBin(BinVal, Action, Count, AtLeast, Weight, PercentCov) ; + InsertNewBin(BinVal, Action, Count, AtLeast, Weight, Name, PercentCov) ; else - report "InsertBin (AddBins/AddCross): ignore bin dropped. It is a subset of prior bin" severity error ; - end if; + Alert(AlertLogIDVar, GetNamePlus(prefix => "in ", suffix => ", ") & "CoveragePkg.InsertBin (AddBins/AddCross):" & + " ignore bin dropped. It is a subset of prior bin", ERROR) ; + end if; elsif Action = COV_ILLEGAL then -- when check only ignore and illegal bins, only action is to report error if CovBinPtr.all(Position).Action = COV_COUNT then - InsertNewBin(BinVal, Action, Count, AtLeast, Weight, PercentCov) ; + InsertNewBin(BinVal, Action, Count, AtLeast, Weight, Name, PercentCov) ; else - report "InsertBin (AddBins/AddCross): illegal bin dropped. It is a subset of prior bin" severity error ; - end if; + Alert(AlertLogIDVar, GetNamePlus(prefix => "in ", suffix => ", ") & "CoveragePkg.InsertBin (AddBins/AddCross):" & + " illegal bin dropped. It is a subset of prior bin", ERROR) ; + end if; end if ; - end if ; -- merging enabled + end if ; -- merging enabled end procedure InsertBin ; ------------------------------------------------------------ procedure AddBins ( ------------------------------------------------------------ + Name : String ; AtLeast : integer ; Weight : integer ; - CovBin : CovBinType + CovBin : CovBinType ) is variable calcAtLeast : integer ; variable calcWeight : integer ; begin CheckBinValLength( 1, "AddBins") ; + GrowBins(CovBin'length) ; for i in CovBin'range loop if CovBin(i).Action = COV_COUNT then @@ -1618,41 +1854,66 @@ package body CoveragePkg is Action => CovBin(i).Action, Count => CovBin(i).Count, AtLeast => calcAtLeast, - Weight => calcWeight + Weight => calcWeight, + Name => Name ) ; end loop ; end procedure AddBins ; ------------------------------------------------------------ - procedure AddBins (AtLeast : integer ; CovBin : CovBinType) is + procedure AddBins ( Name : String ; AtLeast : integer ; CovBin : CovBinType ) is ------------------------------------------------------------ begin - AddBins(AtLeast, 0, CovBin) ; + AddBins(Name, AtLeast, 0, CovBin) ; end procedure AddBins ; - ------------------------------------------------------------ - procedure AddBins (CovBin : CovBinType) is + ------------------------------------------------------------ + procedure AddBins (Name : String ; CovBin : CovBinType) is ------------------------------------------------------------ begin - AddBins(0, 0, CovBin) ; + AddBins(Name, 0, 0, CovBin) ; end procedure AddBins ; ------------------------------------------------------------ - procedure AddCross( - -- Cross existing bins + procedure AddBins ( AtLeast : integer ; Weight : integer ; CovBin : CovBinType ) is ------------------------------------------------------------ - AtLeast : integer ; - Weight : integer ; - Bin1, Bin2 : CovBinType ; - Bin3, Bin4, Bin5, Bin6, Bin7, Bin8, Bin9, Bin10, Bin11, Bin12, Bin13, - Bin14, Bin15, Bin16, Bin17, Bin18, Bin19, Bin20 : CovBinType := NULL_BIN - ) is - constant BIN_LENS : integer_vector := - BinLengths( - Bin1, Bin2, Bin3, Bin4, Bin5, Bin6, Bin7, Bin8, Bin9, Bin10, Bin11, + begin + AddBins("", AtLeast, Weight, CovBin) ; + end procedure AddBins ; + + + ------------------------------------------------------------ + procedure AddBins ( AtLeast : integer ; CovBin : CovBinType ) is + ------------------------------------------------------------ + begin + AddBins("", AtLeast, 0, CovBin) ; + end procedure AddBins ; + + + ------------------------------------------------------------ + procedure AddBins ( CovBin : CovBinType ) is + ------------------------------------------------------------ + begin + AddBins("", 0, 0, CovBin) ; + end procedure AddBins ; + + + ------------------------------------------------------------ + procedure AddCross( + ------------------------------------------------------------ + Name : string ; + AtLeast : integer ; + Weight : integer ; + Bin1, Bin2 : CovBinType ; + Bin3, Bin4, Bin5, Bin6, Bin7, Bin8, Bin9, Bin10, Bin11, Bin12, Bin13, + Bin14, Bin15, Bin16, Bin17, Bin18, Bin19, Bin20 : CovBinType := NULL_BIN + ) is + constant BIN_LENS : integer_vector := + BinLengths( + Bin1, Bin2, Bin3, Bin4, Bin5, Bin6, Bin7, Bin8, Bin9, Bin10, Bin11, Bin12, Bin13, Bin14, Bin15, Bin16, Bin17, Bin18, Bin19, Bin20 ) ; constant NUM_NEW_BINS : integer := CalcNumCrossBins(BIN_LENS) ; @@ -1662,6 +1923,7 @@ package body CoveragePkg is variable calcBinVal : RangeArrayType(BinIndex'range) ; begin CheckBinValLength( BIN_LENS'length, "AddCross") ; + GrowBins(NUM_NEW_BINS) ; calcCount := 0 ; for MatrixIndex in 1 to NUM_NEW_BINS loop @@ -1673,7 +1935,7 @@ package body CoveragePkg is calcBinVal := MergeBinVal(CrossBins) ; calcAtLeast := MergeAtLeast( calcAction, AtLeast, CrossBins) ; calcWeight := MergeWeight ( calcAction, Weight, CrossBins) ; - InsertBin(calcBinVal, calcAction, calcCount, calcAtLeast, calcWeight) ; + InsertBin(calcBinVal, calcAction, calcCount, calcAtLeast, calcWeight, Name) ; IncBinIndex( BinIndex, BIN_LENS) ; -- increment right most one, then if overflow, increment next end loop ; end procedure AddCross ; @@ -1681,15 +1943,15 @@ package body CoveragePkg is ------------------------------------------------------------ procedure AddCross( - -- Cross existing bins ------------------------------------------------------------ - AtLeast : integer ; + Name : string ; + AtLeast : integer ; Bin1, Bin2 : CovBinType ; Bin3, Bin4, Bin5, Bin6, Bin7, Bin8, Bin9, Bin10, Bin11, Bin12, Bin13, Bin14, Bin15, Bin16, Bin17, Bin18, Bin19, Bin20 : CovBinType := NULL_BIN ) is begin - AddCross(AtLeast, 0, + AddCross(Name, AtLeast, 0, Bin1, Bin2, Bin3, Bin4, Bin5, Bin6, Bin7, Bin8, Bin9, Bin10, Bin11, Bin12, Bin13, Bin14, Bin15, Bin16, Bin17, Bin18, Bin19, Bin20 ) ; @@ -1698,14 +1960,62 @@ package body CoveragePkg is ------------------------------------------------------------ procedure AddCross( - -- Cross existing bins ------------------------------------------------------------ + Name : string ; Bin1, Bin2 : CovBinType ; Bin3, Bin4, Bin5, Bin6, Bin7, Bin8, Bin9, Bin10, Bin11, Bin12, Bin13, Bin14, Bin15, Bin16, Bin17, Bin18, Bin19, Bin20 : CovBinType := NULL_BIN ) is begin - AddCross(0, 0, + AddCross(Name, 0, 0, + Bin1, Bin2, Bin3, Bin4, Bin5, Bin6, Bin7, Bin8, Bin9, Bin10, Bin11, + Bin12, Bin13, Bin14, Bin15, Bin16, Bin17, Bin18, Bin19, Bin20 + ) ; + end procedure AddCross ; + + + ------------------------------------------------------------ + procedure AddCross( + ------------------------------------------------------------ + AtLeast : integer ; + Weight : integer ; + Bin1, Bin2 : CovBinType ; + Bin3, Bin4, Bin5, Bin6, Bin7, Bin8, Bin9, Bin10, Bin11, Bin12, Bin13, + Bin14, Bin15, Bin16, Bin17, Bin18, Bin19, Bin20 : CovBinType := NULL_BIN + ) is + begin + AddCross("", AtLeast, Weight, + Bin1, Bin2, Bin3, Bin4, Bin5, Bin6, Bin7, Bin8, Bin9, Bin10, Bin11, + Bin12, Bin13, Bin14, Bin15, Bin16, Bin17, Bin18, Bin19, Bin20 + ) ; + end procedure AddCross ; + + + ------------------------------------------------------------ + procedure AddCross( + ------------------------------------------------------------ + AtLeast : integer ; + Bin1, Bin2 : CovBinType ; + Bin3, Bin4, Bin5, Bin6, Bin7, Bin8, Bin9, Bin10, Bin11, Bin12, Bin13, + Bin14, Bin15, Bin16, Bin17, Bin18, Bin19, Bin20 : CovBinType := NULL_BIN + ) is + begin + AddCross("", AtLeast, 0, + Bin1, Bin2, Bin3, Bin4, Bin5, Bin6, Bin7, Bin8, Bin9, Bin10, Bin11, + Bin12, Bin13, Bin14, Bin15, Bin16, Bin17, Bin18, Bin19, Bin20 + ) ; + end procedure AddCross ; + + + ------------------------------------------------------------ + procedure AddCross( + ------------------------------------------------------------ + Bin1, Bin2 : CovBinType ; + Bin3, Bin4, Bin5, Bin6, Bin7, Bin8, Bin9, Bin10, Bin11, Bin12, Bin13, + Bin14, Bin15, Bin16, Bin17, Bin18, Bin19, Bin20 : CovBinType := NULL_BIN + ) is + begin + AddCross("", 0, 0, Bin1, Bin2, Bin3, Bin4, Bin5, Bin6, Bin7, Bin8, Bin9, Bin10, Bin11, Bin12, Bin13, Bin14, Bin15, Bin16, Bin17, Bin18, Bin19, Bin20 ) ; @@ -1718,9 +2028,11 @@ package body CoveragePkg is begin for i in 1 to NumBins loop deallocate(CovBinPtr(i).BinVal) ; + deallocate(CovBinPtr(i).Name) ; end loop ; deallocate(CovBinPtr) ; - Message.Deallocate ; + DeallocateName ; + DeallocateMessage ; -- Restore internal variables to their default values NumBins := 0 ; OrderCount := 0 ; @@ -1733,7 +2045,15 @@ package body CoveragePkg is CovTarget := 100.0 ; MergingEnable := FALSE ; CountMode := COUNT_FIRST ; + AlertLogIDVar := OSVVM_ALERTLOG_ID ; -- RvSeedInit := FALSE ; + WritePassFailVar := COV_OPT_INIT_PARM_DETECT ; + WriteBinInfoVar := COV_OPT_INIT_PARM_DETECT ; + WriteCountVar := COV_OPT_INIT_PARM_DETECT ; + WriteAnyIllegalVar := COV_OPT_INIT_PARM_DETECT ; + WritePrefixVar.deallocate ; + PassNameVar.deallocate ; + FailNameVar.deallocate ; end procedure deallocate ; @@ -1741,27 +2061,30 @@ package body CoveragePkg is -- Local procedure ICoverIndex( Index : integer ; CovPoint : integer_vector ) is ------------------------------------------------------------ - variable buf : line ; + variable buf : line ; begin -- Update Count, PercentCov CovBinPtr(Index).Count := CovBinPtr(Index).Count + CovBinPtr(Index).action ; + VendorCovBinInc(VendorCovHandleVar, Index); -- VendorCov CovBinPtr(Index).PercentCov := real(CovBinPtr(Index).Count)*100.0/maximum(real(CovBinPtr(Index).AtLeast), 1.0) ; -- OrderCount handling - Statistics OrderCount := OrderCount + 1 ; CovBinPtr(Index).OrderCount := OrderCount + CovBinPtr(Index).OrderCount ; - if CovBinPtr(Index).action = COV_ILLEGAL and IllegalMode /= ILLEGAL_OFF then - write(buf, "%% " & Message.GetName & " Illegal Value: " ) ; - if CovPoint = NULL_INTV then - swrite(buf, "LastIndex Value") ; - else - write(buf, CovPoint) ; - end if ; - write(buf, " is in an illegal Bin. " & "Time: " & time'image(now)) ; - writeline(OUTPUT, buf) ; - if IllegalMode = ILLEGAL_FAILURE then - report Message.GetName & " Illegal Value" severity failure ; - end if ; - end if ; + if CovBinPtr(Index).action = COV_ILLEGAL then + if IllegalMode /= ILLEGAL_OFF then + if CovPoint = NULL_INTV then + alert(AlertLogIDVar, GetNamePlus(prefix => "in ", suffix => ", ") & "CoveragePkg.ICoverLast:" & + " Value randomized is in an illegal bin.", IllegalModeLevel) ; + else + write(buf, CovPoint) ; + alert(AlertLogIDVar, GetNamePlus(prefix => "in ", suffix => ", ") & "CoveragePkg.ICover:" & + " Value " & buf.all & " is in an illegal bin.", IllegalModeLevel) ; + deallocate(buf) ; + end if ; + else + IncAlertCount(AlertLogIDVar, ERROR) ; -- silent alert. + end if ; + end if ; end procedure ICoverIndex ; @@ -1784,26 +2107,27 @@ package body CoveragePkg is ------------------------------------------------------------ procedure ICover( CovPoint : integer_vector) is ------------------------------------------------------------ - variable Found : boolean := FALSE ; begin - if CountMode = COUNT_FIRST and inside(CovPoint, CovBinPtr(LastIndex).BinVal.all) then - ICoverIndex(LastIndex, CovPoint) ; - Found := TRUE ; - end if; - if not Found then + if CovPoint'length /= BinValLength then + Alert(AlertLogIDVar, GetNamePlus(prefix => "in ", suffix => ", ") & "CoveragePkg." & + " ICover: CovPoint length = " & to_string(CovPoint'length) & + " does not match Coverage Bin dimensions = " & to_string(BinValLength), FAILURE) ; + elsif CountMode = COUNT_FIRST and inside(CovPoint, CovBinPtr(LastIndex).BinVal.all) then + ICoverIndex(LastIndex, CovPoint) ; + else CovLoop : for i in 1 to NumBins loop -- skip this CovBin if CovPoint is not in it next CovLoop when not inside(CovPoint, CovBinPtr(i).BinVal.all) ; -- Mark Covered - ICoverIndex(i, CovPoint) ; + ICoverIndex(i, CovPoint) ; exit CovLoop when CountMode = COUNT_FIRST ; -- only find first one end loop CovLoop ; - end if ; + end if ; end procedure ICover ; ------------------------------------------------------------ - procedure SetCovZero is + procedure ClearCov is ------------------------------------------------------------ begin for i in 1 to NumBins loop @@ -1812,8 +2136,15 @@ package body CoveragePkg is CovBinPtr(i).OrderCount := 0 ; end loop ; OrderCount := 0 ; - end procedure SetCovZero ; + end procedure ClearCov ; + ------------------------------------------------------------ + -- deprecated + procedure SetCovZero is + ------------------------------------------------------------ + begin + ClearCov ; + end procedure SetCovZero ; ------------------------------------------------------------ impure function IsInitialized return boolean is @@ -1875,7 +2206,6 @@ package body CoveragePkg is end function GetMinCount ; - ------------------------------------------------------------ impure function GetMaxIndex return integer is ------------------------------------------------------------ @@ -1946,7 +2276,7 @@ package body CoveragePkg is impure function IsCovered ( PercentCov : real ) return boolean is ------------------------------------------------------------ begin - -- assert NumBins >= 1 report "IsCovered: Empty Coverage Model" severity failure ; + -- AlertIf(NumBins < 1, OSVVM_ALERTLOG_ID, "CoveragePkg.IsCovered: Empty Coverage Model", failure) ; return CountCovHoles(PercentCov) = 0 ; end function IsCovered ; @@ -1955,7 +2285,7 @@ package body CoveragePkg is impure function IsCovered return boolean is ------------------------------------------------------------ begin - -- assert NumBins >= 1 report "IsCovered: Empty Coverage Model" severity failure ; + -- AlertIf(NumBins < 1, OSVVM_ALERTLOG_ID, "CoveragePkg.IsCovered: Empty Coverage Model", failure) ; return CountCovHoles(CovTarget) = 0 ; end function IsCovered ; @@ -1968,7 +2298,7 @@ package body CoveragePkg is BinLoop : for i in 1 to NumBins loop if CovBinPtr(i).action = COV_COUNT then ScaledCovGoal := integer(ceil(PercentCov * real(CovBinPtr(i).AtLeast)/100.0)) ; - TotalCovGoal := TotalCovGoal + ScaledCovGoal ; + TotalCovGoal := TotalCovGoal + ScaledCovGoal ; if CovBinPtr(i).Count <= ScaledCovGoal then TotalCovCount := TotalCovCount + CovBinPtr(i).Count ; else @@ -1986,27 +2316,27 @@ package body CoveragePkg is ------------------------------------------------------------ variable TotalCovGoal, TotalCovCount : integer := 0 ; begin - return GetCov( CovTarget ) ; + return GetCov( CovTarget ) ; end function GetCov ; ------------------------------------------------------------ - impure function GetItemCount return integer is + impure function GetItemCount return integer is ------------------------------------------------------------ begin - return ItemCount ; - end function GetItemCount ; + return ItemCount ; + end function GetItemCount ; ------------------------------------------------------------ - impure function GetTotalCovGoal ( PercentCov : real ) return integer is + impure function GetTotalCovGoal ( PercentCov : real ) return integer is ------------------------------------------------------------ variable TotalCovGoal, ScaledCovGoal : integer := 0 ; begin BinLoop : for i in 1 to NumBins loop if CovBinPtr(i).action = COV_COUNT then ScaledCovGoal := integer(ceil(PercentCov * real(CovBinPtr(i).AtLeast)/100.0)) ; - TotalCovGoal := TotalCovGoal + ScaledCovGoal ; + TotalCovGoal := TotalCovGoal + ScaledCovGoal ; end if ; end loop BinLoop ; return TotalCovGoal ; @@ -2014,26 +2344,26 @@ package body CoveragePkg is ------------------------------------------------------------ - impure function GetTotalCovGoal return integer is + impure function GetTotalCovGoal return integer is ------------------------------------------------------------ begin - return GetTotalCovGoal(CovTarget) ; + return GetTotalCovGoal(CovTarget) ; end function GetTotalCovGoal ; ------------------------------------------------------------ - impure function GetLastIndex return integer is + impure function GetLastIndex return integer is ------------------------------------------------------------ begin - return LastIndex ; - end function GetLastIndex ; - + return LastIndex ; + end function GetLastIndex ; + ------------------------------------------------------------ impure function GetHoleBinVal ( ReqHoleNum : integer ; PercentCov : real ) return RangeArrayType is ------------------------------------------------------------ variable HoleCount : integer := 0 ; - variable buf : line ; + variable buf : line ; begin CovLoop : for i in 1 to NumBins loop if CovBinPtr(i).action = COV_COUNT and CovBinPtr(i).PercentCov < PercentCov then @@ -2043,10 +2373,10 @@ package body CoveragePkg is end if ; end if ; end loop CovLoop ; - write(buf, "%%Error GetHoleBinVal did not find hole. " & - "HoleCount = " & integer'image(HoleCount) & - "ReqHoleNum = " & integer'image(ReqHoleNum) & LF) ; - writeline(OUTPUT, buf) ; + Alert(AlertLogIDVar, GetNamePlus(prefix => "in ", suffix => ", ") & "CoveragePkg.GetHoleBinVal:" & + " did not find a coverage hole. HoleCount = " & integer'image(HoleCount) & + " ReqHoleNum = " & integer'image(ReqHoleNum), ERROR + ) ; return CovBinPtr(NumBins).BinVal.all ; end function GetHoleBinVal ; @@ -2118,7 +2448,7 @@ package body CoveragePkg is variable MaxCovPercent : real ; variable MinCovPercent : real ; begin - ItemCount := ItemCount + 1 ; + ItemCount := ItemCount + 1 ; MinCovPercent := GetMinCov ; if ThresholdingEnable then MaxCovPercent := MinCovPercent + CovThreshold ; @@ -2148,7 +2478,7 @@ package body CoveragePkg is -- Caution: DistInt can fail when sum(WeightVec) > 2**31 -- See notes in CalcWeight for REMAIN_EXP LastIndex := 1 + RV.DistInt( WeightVec ) ; -- return range 1 to NumBins - return LastIndex ; + return LastIndex ; end function RandHoleIndex ; @@ -2274,7 +2604,7 @@ package body CoveragePkg is begin return ToRandPoint(GetBinVal(BinIndex)) ; end function GetPoint ; - + ------------------------------------------------------------ impure function GetMinPoint return integer is @@ -2459,62 +2789,254 @@ package body CoveragePkg is result.Weight := CovBinPtr(BinIndex).Weight; return result ; end function GetBin ; - + + -- ------------------------------------------------------------ + impure function GetBinName ( BinIndex : integer; DefaultName : string := "" ) return string is + -- ------------------------------------------------------------ + begin + if CovBinPtr(BinIndex).Name.all /= "" then + return CovBinPtr(BinIndex).Name.all ; + else + return DefaultName ; + end if; + end function GetBinName; ------------------------------------------------------------ -- pt local for now -- file formal parameter not allowed with method - procedure WriteBin ( file f : text ) is + procedure WriteBin ( + file f : text ; + WritePassFail : CovOptionsType ; + WriteBinInfo : CovOptionsType ; + WriteCount : CovOptionsType ; + WriteAnyIllegal : CovOptionsType ; + WritePrefix : string ; + PassName : string ; + FailName : string + ) is ------------------------------------------------------------ - variable buf : line ; + variable buf : line ; begin - WriteBinName(f, "WriteBin: ") ; if NumBins < 1 then - swrite(buf, "%%FATAL, Coverage Model is empty. Nothing to print.") ; - writeline(f, buf) ; - report "Coverage model is empty. Nothing to print." severity failure ; + if WriteBinFileInit or UsingLocalFile then + swrite(buf, WritePrefix & " " & FailName & " ") ; + swrite(buf, GetNamePlus(prefix => "in ", suffix => ", ") & "CoveragePkg.WriteBin: Coverage model is empty. Nothing to print.") ; + writeline(f, buf) ; + end if ; + Alert(AlertLogIDVar, GetNamePlus(prefix => "in ", suffix => ", ") & "CoveragePkg.WriteBin:" & + " Coverage model is empty. Nothing to print.", FAILURE) ; + return ; end if ; + -- Models with Bins + WriteBinName(f, "WriteBin: ", WritePrefix) ; for i in 1 to NumBins loop -- CovBinPtr.all'range - if CovBinPtr(i).count < 0 then - swrite(buf, "%%Illegal Bin:") ; - write(buf, CovBinPtr(i).BinVal.all) ; - write(buf, " Count = " & integer'image(-CovBinPtr(i).count)) ; - write(buf, "" & LF) ; - elsif CovBinPtr(i).action = COV_COUNT then - swrite(buf, "%% Bin:") ; - write(buf, CovBinPtr(i).BinVal.all) ; - write(buf, " Count = " & integer'image(CovBinPtr(i).count)) ; - write(buf, " AtLeast = " & integer'image(CovBinPtr(i).AtLeast)) ; - if WeightMode = WEIGHT or WeightMode = REMAIN_WEIGHT then - -- Print Weight only when it is used - write(buf, " Weight = " & integer'image(CovBinPtr(i).Weight)) ; + if CovBinPtr(i).action = COV_COUNT or + (CovBinPtr(i).action = COV_ILLEGAL and IsEnabled(WriteAnyIllegal)) or + CovBinPtr(i).count < 0 -- Illegal bin with errors + then + -- WriteBin Info + swrite(buf, WritePrefix) ; + if CovBinPtr(i).Name.all /= "" then + swrite(buf, CovBinPtr(i).Name.all & " ") ; + end if ; + if IsEnabled(WritePassFail) then + -- For illegal bins, AtLeast = 0 and count is negative. + if CovBinPtr(i).count >= CovBinPtr(i).AtLeast then + swrite(buf, PassName & ' ') ; + else + swrite(buf, FailName & ' ') ; + end if ; + end if ; + if IsEnabled(WriteBinInfo) then + if CovBinPtr(i).action = COV_COUNT then + swrite(buf, "Bin:") ; + else + swrite(buf, "Illegal Bin:") ; + end if; + write(buf, CovBinPtr(i).BinVal.all) ; + end if ; + if IsEnabled(WriteCount) then + write(buf, " Count = " & integer'image(abs(CovBinPtr(i).count))) ; + write(buf, " AtLeast = " & integer'image(CovBinPtr(i).AtLeast)) ; + if WeightMode = WEIGHT or WeightMode = REMAIN_WEIGHT then + -- Print Weight only when it is used + write(buf, " Weight = " & integer'image(CovBinPtr(i).Weight)) ; + end if ; end if ; writeline(f, buf) ; end if ; end loop ; - swrite(buf, "") ; + swrite(buf, "") ; writeline(f, buf) ; end procedure WriteBin ; - ------------------------------------------------------------ - procedure WriteBin is + procedure WriteBin ( ------------------------------------------------------------ - begin - if WriteBinFileInit then - WriteBin(WriteBinFile) ; + WritePassFail : CovOptionsType := COV_OPT_INIT_PARM_DETECT ; + WriteBinInfo : CovOptionsType := COV_OPT_INIT_PARM_DETECT ; + WriteCount : CovOptionsType := COV_OPT_INIT_PARM_DETECT ; + WriteAnyIllegal : CovOptionsType := COV_OPT_INIT_PARM_DETECT ; + WritePrefix : string := OSVVM_STRING_INIT_PARM_DETECT ; + PassName : string := OSVVM_STRING_INIT_PARM_DETECT ; + FailName : string := OSVVM_STRING_INIT_PARM_DETECT + ) is + constant rWritePassFail : CovOptionsType := ResolveCovWritePassFail(WritePassFail, WritePassFailVar) ; + constant rWriteBinInfo : CovOptionsType := ResolveCovWriteBinInfo(WriteBinInfo, WriteBinInfoVar ) ; + constant rWriteCount : CovOptionsType := ResolveCovWriteCount(WriteCount, WriteCountVar ) ; + constant rWriteAnyIllegal : CovOptionsType := ResolveCovWriteAnyIllegal(WriteAnyIllegal, WriteAnyIllegalVar) ; + constant rWritePrefix : string := ResolveOsvvmWritePrefix(WritePrefix, WritePrefixVar.GetOpt) ; + constant rPassName : string := ResolveOsvvmPassName(PassName, PassNameVar.GetOpt ) ; + constant rFailName : string := ResolveOsvvmFailName(FailName, FailNameVar.GetOpt ) ; + begin + if WriteBinFileInit then + -- Write to Local WriteBinFile - Deprecated, recommend use TranscriptFile instead + WriteBin ( + f => WriteBinFile, + WritePassFail => rWritePassFail, + WriteBinInfo => rWriteBinInfo, + WriteCount => rWriteCount, + WriteAnyIllegal => rWriteAnyIllegal, + WritePrefix => rWritePrefix, + PassName => rPassName, + FailName => rFailName + ) ; + elsif IsTranscriptEnabled then + -- Write to TranscriptFile + WriteBin ( + f => TranscriptFile, + WritePassFail => rWritePassFail, + WriteBinInfo => rWriteBinInfo, + WriteCount => rWriteCount, + WriteAnyIllegal => rWriteAnyIllegal, + WritePrefix => rWritePrefix, + PassName => rPassName, + FailName => rFailName + ) ; + if IsTranscriptMirrored then + -- Mirrored to OUTPUT + WriteBin ( + f => OUTPUT, + WritePassFail => rWritePassFail, + WriteBinInfo => rWriteBinInfo, + WriteCount => rWriteCount, + WriteAnyIllegal => rWriteAnyIllegal, + WritePrefix => rWritePrefix, + PassName => rPassName, + FailName => rFailName + ) ; + end if ; else - WriteBin(OUTPUT) ; + -- Default Write to OUTPUT + WriteBin ( + f => OUTPUT, + WritePassFail => rWritePassFail, + WriteBinInfo => rWriteBinInfo, + WriteCount => rWriteCount, + WriteAnyIllegal => rWriteAnyIllegal, + WritePrefix => rWritePrefix, + PassName => rPassName, + FailName => rFailName + ) ; end if ; + + end procedure WriteBin ; + + + ------------------------------------------------------------ + procedure WriteBin ( -- With LogLevel + ------------------------------------------------------------ + LogLevel : LogType ; + WritePassFail : CovOptionsType := COV_OPT_INIT_PARM_DETECT ; + WriteBinInfo : CovOptionsType := COV_OPT_INIT_PARM_DETECT ; + WriteCount : CovOptionsType := COV_OPT_INIT_PARM_DETECT ; + WriteAnyIllegal : CovOptionsType := COV_OPT_INIT_PARM_DETECT ; + WritePrefix : string := OSVVM_STRING_INIT_PARM_DETECT ; + PassName : string := OSVVM_STRING_INIT_PARM_DETECT ; + FailName : string := OSVVM_STRING_INIT_PARM_DETECT + ) is + begin + if IsLogEnabled(AlertLogIDVar, LogLevel) then + WriteBin ( + WritePassFail => WritePassFail, + WriteBinInfo => WriteBinInfo, + WriteCount => WriteCount, + WriteAnyIllegal => WriteAnyIllegal, + WritePrefix => WritePrefix, + PassName => PassName, + FailName => FailName + ) ; + end if ; + end procedure WriteBin ; -- With LogLevel + + + ------------------------------------------------------------ + procedure WriteBin ( + ------------------------------------------------------------ + FileName : string; + OpenKind : File_Open_Kind := APPEND_MODE ; + WritePassFail : CovOptionsType := COV_OPT_INIT_PARM_DETECT ; + WriteBinInfo : CovOptionsType := COV_OPT_INIT_PARM_DETECT ; + WriteCount : CovOptionsType := COV_OPT_INIT_PARM_DETECT ; + WriteAnyIllegal : CovOptionsType := COV_OPT_INIT_PARM_DETECT ; + WritePrefix : string := OSVVM_STRING_INIT_PARM_DETECT ; + PassName : string := OSVVM_STRING_INIT_PARM_DETECT ; + FailName : string := OSVVM_STRING_INIT_PARM_DETECT + ) is + file LocalWriteBinFile : text open OpenKind is FileName ; + constant rWritePassFail : CovOptionsType := ResolveCovWritePassFail(WritePassFail, WritePassFailVar) ; + constant rWriteBinInfo : CovOptionsType := ResolveCovWriteBinInfo(WriteBinInfo, WriteBinInfoVar ) ; + constant rWriteCount : CovOptionsType := ResolveCovWriteCount(WriteCount, WriteCountVar ) ; + constant rWriteAnyIllegal : CovOptionsType := ResolveCovWriteAnyIllegal(WriteAnyIllegal, WriteAnyIllegalVar) ; + constant rWritePrefix : string := ResolveOsvvmWritePrefix(WritePrefix, WritePrefixVar.GetOpt) ; + constant rPassName : string := ResolveOsvvmPassName(PassName, PassNameVar.GetOpt ) ; + constant rFailName : string := ResolveOsvvmFailName(FailName, FailNameVar.GetOpt ) ; + begin + UsingLocalFile := TRUE ; + WriteBin ( + f => LocalWriteBinFile, + WritePassFail => rWritePassFail, + WriteBinInfo => rWriteBinInfo, + WriteCount => rWriteCount, + WriteAnyIllegal => rWriteAnyIllegal, + WritePrefix => rWritePrefix, + PassName => rPassName, + FailName => rFailName + ); + UsingLocalFile := FALSE ; end procedure WriteBin ; ------------------------------------------------------------ - procedure WriteBin (FileName : string; OpenKind : File_Open_Kind := APPEND_MODE ) is + procedure WriteBin ( -- With LogLevel ------------------------------------------------------------ - file BinFile : text open OpenKind is FileName ; + LogLevel : LogType ; + FileName : string; + OpenKind : File_Open_Kind := APPEND_MODE ; + WritePassFail : CovOptionsType := COV_OPT_INIT_PARM_DETECT ; + WriteBinInfo : CovOptionsType := COV_OPT_INIT_PARM_DETECT ; + WriteCount : CovOptionsType := COV_OPT_INIT_PARM_DETECT ; + WriteAnyIllegal : CovOptionsType := COV_OPT_INIT_PARM_DETECT ; + WritePrefix : string := OSVVM_STRING_INIT_PARM_DETECT ; + PassName : string := OSVVM_STRING_INIT_PARM_DETECT ; + FailName : string := OSVVM_STRING_INIT_PARM_DETECT + ) is begin - WriteBin(BinFile) ; - end procedure WriteBin ; + if IsLogEnabled(AlertLogIDVar, LogLevel) then + UsingLocalFile := TRUE ; + WriteBin ( + FileName => FileName, + OpenKind => OpenKind, + WritePassFail => WritePassFail, + WriteBinInfo => WriteBinInfo, + WriteCount => WriteCount, + WriteAnyIllegal => WriteAnyIllegal, + WritePrefix => WritePrefix, + PassName => PassName, + FailName => FailName + ) ; + UsingLocalFile := FALSE ; + end if ; + end procedure WriteBin ; -- With LogLevel ------------------------------------------------------------ @@ -2522,14 +3044,18 @@ package body CoveragePkg is -- pt local for now -- file formal parameter not allowed with method procedure DumpBin ( file f : text ) is ------------------------------------------------------------ - variable buf : line ; + variable buf : line ; begin WriteBinName(f, "DumpBin: ") ; -- if NumBins < 1 then -- Write(f, "%%FATAL, Coverage Model is empty. Nothing to print." & LF ) ; -- end if ; for i in 1 to NumBins loop -- CovBinPtr.all'range - swrite(buf, "%% Bin:") ; + swrite(buf, "%% ") ; + if CovBinPtr(i).Name.all /= "" then + swrite(buf, CovBinPtr(i).Name.all & " ") ; + end if ; + swrite(buf, "Bin:") ; write(buf, CovBinPtr(i).BinVal.all) ; case CovBinPtr(i).action is when COV_COUNT => swrite(buf, " Count = ") ; @@ -2553,13 +3079,24 @@ package body CoveragePkg is ------------------------------------------------------------ - procedure DumpBin is + procedure DumpBin (LogLevel : LogType := DEBUG) is ------------------------------------------------------------ begin - if WriteBinFileInit then - DumpBin(WriteBinFile) ; - else - DumpBin(OUTPUT) ; + if IsLogEnabled(AlertLogIDVar, LogLevel) then + if WriteBinFileInit then + -- Write to Local WriteBinFile - Deprecated, recommend use TranscriptFile instead + DumpBin(WriteBinFile) ; + elsif IsTranscriptEnabled then + -- Write to TranscriptFile + DumpBin(TranscriptFile) ; + if IsTranscriptMirrored then + -- Mirrored to OUTPUT + DumpBin(OUTPUT) ; + end if ; + else + -- Default Write to OUTPUT + DumpBin(OUTPUT) ; + end if ; end if ; end procedure DumpBin ; @@ -2568,17 +3105,28 @@ package body CoveragePkg is -- pt local procedure WriteCovHoles ( file f : text; PercentCov : real := 100.0 ) is ------------------------------------------------------------ - variable buf : line ; + variable buf : line ; begin - WriteBinName(f, "WriteCovHoles: ") ; if NumBins < 1 then - swrite(buf, "%%FATAL, Coverage Model is empty. Nothing to print.") ; - writeline(f, buf) ; - report "Coverage model is empty. Nothing to print." severity failure ; + if WriteBinFileInit or UsingLocalFile then + -- Duplicate Alert in specified file + swrite(buf, "%% Alert FAILURE " & GetNamePlus(prefix => "in ", suffix => ", ") & "CoveragePkg.WriteCovHoles:" & + " coverage model empty. Nothing to print.") ; + writeline(f, buf) ; + end if ; + Alert(AlertLogIDVar, GetNamePlus(prefix => "in ", suffix => ", ") & "CoveragePkg.WriteCovHoles:" & + " coverage model empty. Nothing to print.", FAILURE) ; + return ; end if ; + -- Models with Bins + WriteBinName(f, "WriteCovHoles: ") ; CovLoop : for i in 1 to NumBins loop if CovBinPtr(i).action = COV_COUNT and CovBinPtr(i).PercentCov < PercentCov then - swrite(buf, "%% Bin:") ; + swrite(buf, "%% ") ; + if CovBinPtr(i).Name.all /= "" then + swrite(buf, CovBinPtr(i).Name.all & " ") ; + end if ; + swrite(buf, "Bin:") ; write(buf, CovBinPtr(i).BinVal.all) ; write(buf, " Count = " & integer'image(CovBinPtr(i).Count)) ; write(buf, " AtLeast = " & integer'image(CovBinPtr(i).AtLeast)) ; @@ -2589,31 +3137,48 @@ package body CoveragePkg is writeline(f, buf) ; end if ; end loop CovLoop ; - swrite(buf, "") ; + swrite(buf, "") ; writeline(f, buf) ; end procedure WriteCovHoles ; ------------------------------------------------------------ - procedure WriteCovHoles is + procedure WriteCovHoles ( PercentCov : real ) is ------------------------------------------------------------ begin if WriteBinFileInit then - WriteCovHoles(WriteBinFile, CovTarget) ; + -- Write to Local WriteBinFile - Deprecated, recommend use TranscriptFile instead + WriteCovHoles(WriteBinFile, PercentCov) ; + elsif IsTranscriptEnabled then + -- Write to TranscriptFile + WriteCovHoles(TranscriptFile, PercentCov) ; + if IsTranscriptMirrored then + -- Mirrored to OUTPUT + WriteCovHoles(OUTPUT, PercentCov) ; + end if ; else - WriteCovHoles(OUTPUT, CovTarget) ; + -- Default Write to OUTPUT + WriteCovHoles(OUTPUT, PercentCov) ; end if; end procedure WriteCovHoles ; + + ------------------------------------------------------------ + procedure WriteCovHoles ( LogLevel : LogType := ALWAYS ) is + ------------------------------------------------------------ + begin + if IsLogEnabled(AlertLogIDVar, LogLevel) then + WriteCovHoles(CovTarget) ; + end if; + end procedure WriteCovHoles ; + ------------------------------------------------------------ - procedure WriteCovHoles ( PercentCov : real ) is + procedure WriteCovHoles ( LogLevel : LogType ; PercentCov : real ) is ------------------------------------------------------------ begin - if WriteBinFileInit then - WriteCovHoles(WriteBinFile, PercentCov) ; - else - WriteCovHoles(OUTPUT, PercentCov) ; + if IsLogEnabled(AlertLogIDVar, LogLevel) then + WriteCovHoles(PercentCov) ; end if; end procedure WriteCovHoles ; @@ -2623,7 +3188,19 @@ package body CoveragePkg is ------------------------------------------------------------ file CovHoleFile : text open OpenKind is FileName ; begin + UsingLocalFile := TRUE ; WriteCovHoles(CovHoleFile, CovTarget) ; + UsingLocalFile := FALSE ; + end procedure WriteCovHoles ; + + + ------------------------------------------------------------ + procedure WriteCovHoles ( LogLevel : LogType ; FileName : string; OpenKind : File_Open_Kind := APPEND_MODE ) is + ------------------------------------------------------------ + begin + if IsLogEnabled(AlertLogIDVar, LogLevel) then + WriteCovHoles(FileName, OpenKind) ; + end if; end procedure WriteCovHoles ; @@ -2632,104 +3209,159 @@ package body CoveragePkg is ------------------------------------------------------------ file CovHoleFile : text open OpenKind is FileName ; begin - WriteCovHoles(CovHoleFile, PercentCov) ; + UsingLocalFile := TRUE ; + WriteCovHoles(CovHoleFile, PercentCov) ; + UsingLocalFile := FALSE ; + end procedure WriteCovHoles ; + + + ------------------------------------------------------------ + procedure WriteCovHoles ( LogLevel : LogType ; FileName : string; PercentCov : real ; OpenKind : File_Open_Kind := APPEND_MODE ) is + ------------------------------------------------------------ + begin + if IsLogEnabled(AlertLogIDVar, LogLevel) then + WriteCovHoles(FileName, PercentCov, OpenKind) ; + end if; end procedure WriteCovHoles ; ------------------------------------------------------------ -- pt local - impure function FindBin ( + impure function FindExactBin ( + -- find an exact match to a bin wrt BinVal, Action, AtLeast, Weight, and Name ------------------------------------------------------------ Merge : boolean ; BinVal : RangeArrayType ; - Action : integer + Action : integer ; + AtLeast : integer ; + Weight : integer ; + Name : string ) return integer is begin - if Merge then + if Merge then for i in 1 to NumBins loop - if BinVal = CovBinPtr(i).BinVal.all and Action = CovBinPtr(i).Action then + if (BinVal = CovBinPtr(i).BinVal.all) and (Action = CovBinPtr(i).Action) and + (AtLeast = CovBinPtr(i).AtLeast) and (Weight = CovBinPtr(i).Weight) and + (Name = CovBinPtr(i).Name.all) then return i ; end if; end loop ; - end if ; + end if ; return 0 ; - end function FindBin ; + end function FindExactBin ; ------------------------------------------------------------ -- pt local - procedure ReadCovVars (file CovDbFile : text; Good : out boolean ) is + procedure read ( ------------------------------------------------------------ - variable buf : line ; - variable Empty : boolean ; - variable ReadValid : boolean ; - variable GoodLoop1 : boolean ; + buf : inout line ; + NamePtr : inout line ; + NameLength : in integer ; + ReadValid : out boolean + ) is + variable Name : string(1 to NameLength) ; + begin + if NameLength > 0 then + read(buf, Name, ReadValid) ; + NamePtr := new string'(Name) ; + else + ReadValid := TRUE ; + NamePtr := new string'("") ; + end if ; + end procedure read ; - variable iSeed : RandomSeedType ; - variable iIllegalMode : integer ; - variable iWeightMode : integer ; - variable iWeightScale : real ; - variable iCovThreshold : real ; - variable iCountMode : integer ; - variable iNumberOfMessages : integer ; - variable iThresholdingEnable : boolean ; - variable iCovTarget : real ; - variable iMergingEnable : boolean ; - begin - ReadLoop0 : while not EndFile(CovDbFile) loop + ------------------------------------------------------------ + -- pt local + procedure ReadCovVars (file CovDbFile : text; Good : out boolean ) is + ------------------------------------------------------------ + variable buf : line ; + variable Empty : boolean ; + variable MultiLineComment : boolean := FALSE ; + variable ReadValid : boolean ; + variable GoodLoop1 : boolean ; + variable iSeed : RandomSeedType ; + variable iIllegalMode : integer ; + variable iWeightMode : integer ; + variable iWeightScale : real ; + variable iCovThreshold : real ; + variable iCountMode : integer ; + variable iNumberOfMessages : integer ; + variable iThresholdingEnable : boolean ; + variable iCovTarget : real ; + variable iMergingEnable : boolean ; + begin + -- ReadLoop0 : while not EndFile(CovDbFile) loop + ReadLoop0 : loop -- allows emulation of "return when" + -- ReadLine to Get Coverage Model Name, skip blank and comment lines, fails when file empty + exit when AlertIf(AlertLogIDVar, EndFile(CovDbFile), GetNamePlus(prefix => "in ", suffix => ", ") & + "CoveragePkg.ReadCovDb: No Coverage Data to read", FAILURE) ; ReadLine(CovDbFile, buf) ; - EmptyOrCommentLine(buf, Empty) ; + EmptyOrCommentLine(buf, Empty, MultiLineComment) ; next when Empty ; - - if buf.all /= "CoveragePkg_Not_Named" then - Message.SetName(buf.all) ; - end if ; + + if buf.all /= "Coverage_Model_Not_Named" then + SetName(buf.all) ; + end if ; exit ReadLoop0 ; end loop ReadLoop0 ; - - ReadLoop1 : while not EndFile(CovDbFile) loop + + -- ReadLoop1 : while not EndFile(CovDbFile) loop + ReadLoop1 : loop + -- ReadLine to Get Variables, skip blank and comment lines, fails when file empty + exit when AlertIf(AlertLogIDVar, EndFile(CovDbFile), GetNamePlus(prefix => "in ", suffix => ", ") & + "CoveragePkg.ReadCovDb: Coverage DB File Incomplete", FAILURE) ; ReadLine(CovDbFile, buf) ; - EmptyOrCommentLine(buf, Empty) ; + EmptyOrCommentLine(buf, Empty, MultiLineComment) ; next when Empty ; read(buf, iSeed, ReadValid) ; - exit ReadLoop1 when failed(not ReadValid, "ReadCovDb: Failed while reading Seed") ; + exit when AlertIfNot(AlertLogIDVar, ReadValid, GetNamePlus(prefix => "in ", suffix => ", ") & + "CoveragePkg.ReadCovDb: Failed while reading Seed", FAILURE) ; RV.SetSeed( iSeed ) ; RvSeedInit := TRUE ; read(buf, iCovThreshold, ReadValid) ; - exit ReadLoop1 when failed(not ReadValid, "ReadCovDb: Failed while reading CovThreshold") ; + exit when AlertIfNot(AlertLogIDVar, ReadValid, GetNamePlus(prefix => "in ", suffix => ", ") & + "CoveragePkg.ReadCovDb: Failed while reading CovThreshold", FAILURE) ; CovThreshold := iCovThreshold ; read(buf, iIllegalMode, ReadValid) ; - exit ReadLoop1 when failed(not ReadValid, "ReadCovDb: Failed while reading IllegalMode") ; - IllegalMode := IllegalModeType'val( iIllegalMode ) ; + exit when AlertIfNot(AlertLogIDVar, ReadValid, GetNamePlus(prefix => "in ", suffix => ", ") & + "CoveragePkg.ReadCovDb: Failed while reading IllegalMode", FAILURE) ; + SetIllegalMode(IllegalModeType'val( iIllegalMode )) ; read(buf, iWeightMode, ReadValid) ; - exit ReadLoop1 when failed(not ReadValid, "ReadCovDb: Failed while reading WeightMode") ; + exit when AlertIfNot(AlertLogIDVar, ReadValid, GetNamePlus(prefix => "in ", suffix => ", ") & + "CoveragePkg.ReadCovDb: Failed while reading WeightMode", FAILURE) ; WeightMode := WeightModeType'val( iWeightMode ) ; read(buf, iWeightScale, ReadValid) ; - exit ReadLoop1 when failed(not ReadValid, "ReadCovDb: Failed while reading WeightScale") ; + exit when AlertIfNot(AlertLogIDVar, ReadValid, GetNamePlus(prefix => "in ", suffix => ", ") & + "CoveragePkg.ReadCovDb: Failed while reading WeightScale", FAILURE) ; WeightScale := iWeightScale ; read(buf, iCountMode, ReadValid) ; - exit ReadLoop1 when failed(not ReadValid, "ReadCovDb: Failed while reading CountMode") ; + exit when AlertIfNot(AlertLogIDVar, ReadValid, GetNamePlus(prefix => "in ", suffix => ", ") & + "CoveragePkg.ReadCovDb: Failed while reading CountMode", FAILURE) ; CountMode := CountModeType'val( iCountMode ) ; read(buf, iThresholdingEnable, ReadValid) ; - exit ReadLoop1 when failed(not ReadValid, "ReadCovDb: Failed while reading CountMode") ; + exit when AlertIfNot(AlertLogIDVar, ReadValid, GetNamePlus(prefix => "in ", suffix => ", ") & + "CoveragePkg.ReadCovDb: Failed while reading CountMode", FAILURE) ; ThresholdingEnable := iThresholdingEnable ; read(buf, iCovTarget, ReadValid) ; - exit ReadLoop1 when failed(not ReadValid, "ReadCovDb: Failed while reading CountMode") ; + exit when AlertIfNot(AlertLogIDVar, ReadValid, GetNamePlus(prefix => "in ", suffix => ", ") & + "CoveragePkg.ReadCovDb: Failed while reading CountMode", FAILURE) ; CovTarget := iCovTarget ; read(buf, iMergingEnable, ReadValid) ; - exit ReadLoop1 when failed(not ReadValid, "ReadCovDb: Failed while reading CountMode") ; + exit when AlertIfNot(AlertLogIDVar, ReadValid, GetNamePlus(prefix => "in ", suffix => ", ") & + "CoveragePkg.ReadCovDb: Failed while reading CountMode", FAILURE) ; MergingEnable := iMergingEnable ; exit ReadLoop1 ; @@ -2737,16 +3369,22 @@ package body CoveragePkg is GoodLoop1 := ReadValid ; - ReadLoop2 : while not EndFile(CovDbFile) loop + -- ReadLoop2 : while not EndFile(CovDbFile) loop + ReadLoop2 : while ReadValid loop + -- ReadLine to Coverage Model Header WriteBin Message, skip blank and comment lines, fails when file empty + exit when AlertIf(AlertLogIDVar, EndFile(CovDbFile), GetNamePlus(prefix => "in ", suffix => ", ") & + "CoveragePkg.ReadCovDb: Coverage DB File Incomplete", FAILURE) ; ReadLine(CovDbFile, buf) ; - EmptyOrCommentLine(buf, Empty) ; + EmptyOrCommentLine(buf, Empty, MultiLineComment) ; next when Empty ; read(buf, iNumberOfMessages, ReadValid) ; - exit ReadLoop2 when failed(not ReadValid, "ReadCovDb: Failed while reading NumberOfMessages") ; + exit when AlertIfNot(AlertLogIDVar, ReadValid, GetNamePlus(prefix => "in ", suffix => ", ") & + "CoveragePkg.ReadCovDb: Failed while reading NumberOfMessages", FAILURE) ; for i in 1 to iNumberOfMessages loop - exit ReadLoop2 when failed(EndFile(CovDbFile), "ReadCovDb: End of File while reading Messages") ; + exit when AlertIf(AlertLogIDVar, EndFile(CovDbFile), GetNamePlus(prefix => "in ", suffix => ", ") & + "CoveragePkg.ReadCovDb: End of File while reading Messages", FAILURE) ; ReadLine(CovDbFile, buf) ; SetMessage(buf.all) ; end loop ; @@ -2767,22 +3405,26 @@ package body CoveragePkg is variable NumLines : out integer ; variable Good : out boolean ) is - variable buf : line ; - variable ReadValid : boolean ; - variable Empty : boolean ; + variable buf : line ; + variable ReadValid : boolean ; + variable Empty : boolean ; + variable MultiLineComment : boolean := FALSE ; begin - ReadLoop : while not EndFile(CovDbFile) loop + ReadLoop : loop + -- ReadLine to RangeItems NumLines, skip blank and comment lines, fails when file empty + exit when AlertIf(AlertLogIDVar, EndFile(CovDbFile), GetNamePlus(prefix => "in ", suffix => ", ") & + "CoveragePkg.ReadCovDb: Coverage DB File Incomplete", FAILURE) ; ReadLine(CovDbFile, buf) ; - EmptyOrCommentLine(buf, Empty) ; + EmptyOrCommentLine(buf, Empty, MultiLineComment) ; next when Empty ; read(buf, NumRangeItems, ReadValid) ; - exit ReadLoop when failed(not ReadValid, "ReadCovDb: Failed while reading NumRangeItems") ; + exit when AlertIfNot(AlertLogIDVar, ReadValid, GetNamePlus(prefix => "in ", suffix => ", ") & + "CoveragePkg.ReadCovDb: Failed while reading NumRangeItems", FAILURE) ; read(buf, NumLines, ReadValid) ; - assert ReadValid - report "ReadCovDb: Failed while reading NumLines" - severity failure ; + exit when AlertIfNot(AlertLogIDVar, ReadValid, GetNamePlus(prefix => "in ", suffix => ", ") & + "CoveragePkg.ReadCovDb: Failed while reading NumLines", FAILURE) ; exit ; end loop ReadLoop ; Good := ReadValid ; @@ -2797,47 +3439,72 @@ package body CoveragePkg is constant NumRangeItems : in integer ; constant NumLines : in integer ; constant Merge : in boolean ; - variable Good : out boolean + variable Good : out boolean ) is - variable buf : line ; - variable Empty : boolean ; - variable ReadValid : boolean ; + variable buf : line ; + variable Empty : boolean ; + variable MultiLineComment : boolean := FALSE ; + variable ReadValid : boolean ; -- Format: Action Count min1 max1 min2 max2 .... - variable Action : integer ; - variable Count : integer ; - variable BinVal : RangeArrayType(1 to NumRangeItems) ; - variable index : integer ; - variable AtLeast : integer ; - variable Weight : integer ; - variable PercentCov : real ; + variable Action : integer ; + variable Count : integer ; + variable BinVal : RangeArrayType(1 to NumRangeItems) ; + variable index : integer ; + variable AtLeast : integer ; + variable Weight : integer ; + variable PercentCov : real ; + variable NameLength : integer ; + variable SkipBlank : character ; + variable NamePtr : line ; begin GrowBins(NumLines) ; ReadLoop : for i in 1 to NumLines loop - exit ReadLoop when failed(EndFile(CovDbFile), "ReadCovDb: Did not read specified number of lines") ; - ReadLine(CovDbFile, buf) ; - EmptyOrCommentLine(buf, Empty) ; - next when Empty ; -- replace with EmptyLine(buf) + + GetValidLineLoop: loop + exit ReadLoop when AlertIf(AlertLogIDVar, EndFile(CovDbFile), GetNamePlus(prefix => "in ", suffix => ", ") & + "CoveragePkg.ReadCovDb: Did not read specified number of lines", FAILURE) ; + ReadLine(CovDbFile, buf) ; + EmptyOrCommentLine(buf, Empty, MultiLineComment) ; + next GetValidLineLoop when Empty ; -- replace with EmptyLine(buf) + exit GetValidLineLoop ; + end loop ; read(buf, Action, ReadValid) ; - exit ReadLoop when failed(not ReadValid, "ReadCovDb: Failed while reading Action") ; + exit ReadLoop when AlertIfNot(AlertLogIDVar, ReadValid, GetNamePlus(prefix => "in ", suffix => ", ") & + "CoveragePkg.ReadCovDb: Failed while reading Action", FAILURE) ; read(buf, Count, ReadValid) ; - exit ReadLoop when failed(not ReadValid, "ReadCovDb: Failed while reading Count") ; + exit ReadLoop when AlertIfNot(AlertLogIDVar, ReadValid, GetNamePlus(prefix => "in ", suffix => ", ") & + "CoveragePkg.ReadCovDb: Failed while reading Count", FAILURE) ; read(buf, AtLeast, ReadValid) ; - exit ReadLoop when failed(not ReadValid, "ReadCovDb: Failed while reading AtLeast") ; + exit ReadLoop when AlertIfNot(AlertLogIDVar, ReadValid, GetNamePlus(prefix => "in ", suffix => ", ") & + "CoveragePkg.ReadCovDb: Failed while reading AtLeast", FAILURE) ; read(buf, Weight, ReadValid) ; - exit ReadLoop when failed(not ReadValid, "ReadCovDb: Failed while reading Weight") ; + exit ReadLoop when AlertIfNot(AlertLogIDVar, ReadValid, GetNamePlus(prefix => "in ", suffix => ", ") & + "CoveragePkg.ReadCovDb: Failed while reading Weight", FAILURE) ; read(buf, PercentCov, ReadValid) ; - exit ReadLoop when failed(not ReadValid, "ReadCovDb: Failed while reading PercentCov") ; + exit ReadLoop when AlertIfNot(AlertLogIDVar, ReadValid, GetNamePlus(prefix => "in ", suffix => ", ") & + "CoveragePkg.ReadCovDb: Failed while reading PercentCov", FAILURE) ; read(buf, BinVal, ReadValid) ; - exit ReadLoop when failed(not ReadValid, "ReadCovDb: Failed while reading BinVal") ; - - index := FindBin(Merge, BinVal, Action) ; - if index > 0 then -- merge it + exit ReadLoop when AlertIfNot(AlertLogIDVar, ReadValid, GetNamePlus(prefix => "in ", suffix => ", ") & + "CoveragePkg.ReadCovDb: Failed while reading BinVal", FAILURE) ; + read(buf, NameLength, ReadValid) ; + exit ReadLoop when AlertIfNot(AlertLogIDVar, ReadValid, GetNamePlus(prefix => "in ", suffix => ", ") & + "CoveragePkg.ReadCovDb: Failed while reading Bin Name Length", FAILURE) ; + read(buf, SkipBlank, ReadValid) ; + exit ReadLoop when AlertIfNot(AlertLogIDVar, ReadValid, GetNamePlus(prefix => "in ", suffix => ", ") & + "CoveragePkg.ReadCovDb: Failed while reading Bin Name Length", FAILURE) ; + read(buf, NamePtr, NameLength, ReadValid) ; + exit ReadLoop when AlertIfNot(AlertLogIDVar, ReadValid, GetNamePlus(prefix => "in ", suffix => ", ") & + "CoveragePkg.ReadCovDb: Failed while reading Bin Name", FAILURE) ; + index := FindExactBin(Merge, BinVal, Action, AtLeast, Weight, NamePtr.all) ; + if index > 0 then + -- Bin is an exact match so only merge the count values CovBinPtr(index).Count := CovBinPtr(index).Count + Count ; CovBinPtr(index).PercentCov := real(CovBinPtr(index).Count)*100.0/maximum(real(CovBinPtr(index).AtLeast), 1.0) ; else - InsertNewBin(BinVal, Action, Count, AtLeast, Weight, PercentCov) ; - end if ; + InsertNewBin(BinVal, Action, Count, AtLeast, Weight, NamePtr.all, PercentCov) ; + end if ; + deallocate(NamePtr) ; end loop ReadLoop ; Good := ReadValid ; end ReadCovDbDataBase ; @@ -2853,10 +3520,10 @@ package body CoveragePkg is variable NumLines : integer ; variable ReadValid : boolean ; begin - if not Merge then + if not Merge then Deallocate ; -- remove any old bins end if ; - + ReadLoop : loop -- Read coverage private variables to the file ReadCovVars(CovDbFile, ReadValid) ; @@ -2885,41 +3552,37 @@ package body CoveragePkg is ------------------------------------------------------------ -- pt local - procedure WriteCovVars (file CovDbFile : text ) is + procedure WriteCovDbVars (file CovDbFile : text ) is ------------------------------------------------------------ variable buf : line ; begin -- write coverage private variables to the file - if Message.GetName /= "" then - write(buf, Message.GetName) ; - else - swrite(buf, "CoveragePkg_Not_Named") ; - end if ; - writeline(CovDbFile, buf) ; - + swrite(buf, CovNameVar.Get("Coverage_Model_Not_Named")) ; + writeline(CovDbFile, buf) ; + write(buf, RV.GetSeed ) ; write(buf, ' ') ; - write(buf, CovThreshold) ; + write(buf, CovThreshold, RIGHT, 0, 5) ; write(buf, ' ') ; write(buf, IllegalModeType'pos(IllegalMode)) ; write(buf, ' ') ; write(buf, WeightModeType'pos(WeightMode)) ; write(buf, ' ') ; - write(buf, WeightScale) ; + write(buf, WeightScale, RIGHT, 0, 6) ; write(buf, ' ') ; write(buf, CountModeType'pos(CountMode)) ; write(buf, ' ') ; write(buf, ThresholdingEnable) ; -- boolean write(buf, ' ') ; - write(buf, CovTarget) ; -- Real + write(buf, CovTarget, RIGHT, 0, 6) ; -- Real write(buf, ' ') ; write(buf, MergingEnable) ; -- boolean write(buf, ' ') ; writeline(CovDbFile, buf) ; - write(buf, Message.GetMessageCount ) ; + write(buf, CovMessageVar.GetCount ) ; writeline(CovDbFile, buf) ; - WriteBinName(CovDbFile, "", "") ; - end procedure WriteCovVars ; + WriteMessage(CovDbFile, CovMessageVar) ; + end procedure WriteCovDbVars ; ------------------------------------------------------------ @@ -2930,7 +3593,7 @@ package body CoveragePkg is variable buf : line ; begin -- write Cover variables to the file - WriteCovVars( CovDbFile ) ; + WriteCovDbVars( CovDbFile ) ; -- write NumRangeItems, NumLines write(buf, CovBinPtr(1).BinVal'length) ; @@ -2948,9 +3611,13 @@ package body CoveragePkg is write(buf, ' ') ; write(buf, CovBinPtr(LineCount).Weight) ; write(buf, ' ') ; - write(buf, CovBinPtr(LineCount).PercentCov) ; + write(buf, CovBinPtr(LineCount).PercentCov, RIGHT, 0, 4) ; write(buf, ' ') ; WriteBinVal(buf, CovBinPtr(LineCount).BinVal.all) ; + write(buf, ' ') ; + write(buf, CovBinPtr(LineCount).Name'length) ; + write(buf, ' ') ; + write(buf, CovBinPtr(LineCount).Name.all) ; writeline(CovDbFile, buf) ; end loop WriteLoop ; end procedure WriteCovDb ; @@ -2962,7 +3629,12 @@ package body CoveragePkg is -- Format: Action Count min1 max1 min2 max2 file CovDbFile : text open OpenKind is FileName ; begin - WriteCovDb(CovDbFile) ; + if NumBins >= 1 then + WriteCovDb(CovDbFile) ; + else + Alert(AlertLogIDVar, GetNamePlus(prefix => "in ", suffix => ", ") & + "CoveragePkg.WriteCovDb: no bins defined ", FAILURE) ; + end if ; end procedure WriteCovDb ; @@ -2996,118 +3668,127 @@ package body CoveragePkg is end function GetErrorCount ; ------------------------------------------------------------ - -- These support the older AddBins(GenCross(...)) methodology + -- These support usage of cross coverage constants + -- Also support the older AddBins(GenCross(...)) methodology -- which has been replaced by AddCross ------------------------------------------------------------ - procedure AddBins (CovBin : CovMatrix2Type) is + procedure AddCross (CovBin : CovMatrix2Type ; Name : String := "") is ------------------------------------------------------------ begin + CheckBinValLength(2, "AddCross") ; GrowBins(CovBin'length) ; for i in CovBin'range loop InsertBin( CovBin(i).BinVal, CovBin(i).Action, CovBin(i).Count, - CovBin(i).AtLeast, CovBin(i).Weight + CovBin(i).AtLeast, CovBin(i).Weight, Name ) ; end loop ; - end procedure AddBins ; + end procedure AddCross ; ------------------------------------------------------------ - procedure AddBins (CovBin : CovMatrix3Type) is + procedure AddCross (CovBin : CovMatrix3Type ; Name : String := "") is ------------------------------------------------------------ begin + CheckBinValLength(3, "AddCross") ; GrowBins(CovBin'length) ; for i in CovBin'range loop InsertBin( CovBin(i).BinVal, CovBin(i).Action, CovBin(i).Count, - CovBin(i).AtLeast, CovBin(i).Weight + CovBin(i).AtLeast, CovBin(i).Weight, Name ) ; end loop ; - end procedure AddBins ; + end procedure AddCross ; ------------------------------------------------------------ - procedure AddBins (CovBin : CovMatrix4Type) is + procedure AddCross (CovBin : CovMatrix4Type ; Name : String := "") is ------------------------------------------------------------ begin + CheckBinValLength(4, "AddCross") ; GrowBins(CovBin'length) ; for i in CovBin'range loop InsertBin( CovBin(i).BinVal, CovBin(i).Action, CovBin(i).Count, - CovBin(i).AtLeast, CovBin(i).Weight + CovBin(i).AtLeast, CovBin(i).Weight, Name ) ; end loop ; - end procedure AddBins ; + end procedure AddCross ; ------------------------------------------------------------ - procedure AddBins (CovBin : CovMatrix5Type) is + procedure AddCross (CovBin : CovMatrix5Type ; Name : String := "") is ------------------------------------------------------------ begin + CheckBinValLength(5, "AddCross") ; GrowBins(CovBin'length) ; for i in CovBin'range loop InsertBin( CovBin(i).BinVal, CovBin(i).Action, CovBin(i).Count, - CovBin(i).AtLeast, CovBin(i).Weight + CovBin(i).AtLeast, CovBin(i).Weight, Name ) ; end loop ; - end procedure AddBins ; + end procedure AddCross ; ------------------------------------------------------------ - procedure AddBins (CovBin : CovMatrix6Type) is + procedure AddCross (CovBin : CovMatrix6Type ; Name : String := "") is ------------------------------------------------------------ begin + CheckBinValLength(6, "AddCross") ; GrowBins(CovBin'length) ; for i in CovBin'range loop InsertBin( CovBin(i).BinVal, CovBin(i).Action, CovBin(i).Count, - CovBin(i).AtLeast, CovBin(i).Weight + CovBin(i).AtLeast, CovBin(i).Weight, Name ) ; end loop ; - end procedure AddBins ; + end procedure AddCross ; ------------------------------------------------------------ - procedure AddBins (CovBin : CovMatrix7Type) is + procedure AddCross (CovBin : CovMatrix7Type ; Name : String := "") is ------------------------------------------------------------ begin + CheckBinValLength(7, "AddCross") ; GrowBins(CovBin'length) ; for i in CovBin'range loop InsertBin( CovBin(i).BinVal, CovBin(i).Action, CovBin(i).Count, - CovBin(i).AtLeast, CovBin(i).Weight + CovBin(i).AtLeast, CovBin(i).Weight, Name ) ; end loop ; - end procedure AddBins ; + end procedure AddCross ; ------------------------------------------------------------ - procedure AddBins (CovBin : CovMatrix8Type) is + procedure AddCross (CovBin : CovMatrix8Type ; Name : String := "") is ------------------------------------------------------------ begin + CheckBinValLength(8, "AddCross") ; GrowBins(CovBin'length) ; for i in CovBin'range loop InsertBin( CovBin(i).BinVal, CovBin(i).Action, CovBin(i).Count, - CovBin(i).AtLeast, CovBin(i).Weight + CovBin(i).AtLeast, CovBin(i).Weight, Name ) ; end loop ; - end procedure AddBins ; + end procedure AddCross ; ------------------------------------------------------------ - procedure AddBins (CovBin : CovMatrix9Type) is + procedure AddCross (CovBin : CovMatrix9Type ; Name : String := "") is ------------------------------------------------------------ begin + CheckBinValLength(9, "AddCross") ; GrowBins(CovBin'length) ; for i in CovBin'range loop InsertBin( CovBin(i).BinVal, CovBin(i).Action, CovBin(i).Count, - CovBin(i).AtLeast, CovBin(i).Weight + CovBin(i).AtLeast, CovBin(i).Weight, Name ) ; end loop ; - end procedure AddBins ; + end procedure AddCross ; -- ------------------------------------------------------------ -- ------------------------------------------------------------ @@ -3250,8 +3931,8 @@ package body CoveragePkg is CovBinPtr(BinIndex).Count ) ; when others => - report "Selected Weight Mode not Supported with depricated RandCovPoint(AtLeast), see RandCovPoint(PercentCov)" - severity failure ; + Alert(AlertLogIDVar, GetNamePlus(prefix => "in ", suffix => ", ") & "CoveragePkg.CalcWeight:" & + " Selected Weight Mode not supported with deprecated RandCovPoint(AtLeast), see RandCovPoint(PercentCov)", FAILURE) ; return MaxAtLeast - CovBinPtr(BinIndex).Count ; end case ; @@ -3267,7 +3948,7 @@ package body CoveragePkg is variable WeightVec : integer_vector(0 to NumBins-1) ; -- Prep for change to DistInt variable MinCount, AdjAtLeast, MaxAtLeast : integer ; begin - ItemCount := ItemCount + 1 ; + ItemCount := ItemCount + 1 ; MinCount := GetMinCov ; -- iAtLeast := integer(ceil(CovTarget * real(AtLeast)/100.0)) ; if ThresholdingEnable then @@ -3300,7 +3981,7 @@ package body CoveragePkg is end loop CovLoop ; -- DistInt returns integer range 0 to Numbins-1 LastIndex := 1 + RV.DistInt( WeightVec ) ; -- return range 1 to NumBins - return LastIndex ; + return LastIndex ; end function RandHoleIndex ; ------------------------------------------------------------ @@ -3342,7 +4023,7 @@ package body CoveragePkg is impure function GetHoleBinVal ( ReqHoleNum : integer ; AtLeast : integer ) return RangeArrayType is ------------------------------------------------------------ variable HoleCount : integer := 0 ; - variable buf : line ; + variable buf : line ; begin CovLoop : for i in 1 to NumBins loop -- if CovBinPtr(i).action = COV_COUNT and CovBinPtr(i).Count < minimum(AtLeast, CovBinPtr(i).AtLeast) then @@ -3353,10 +4034,10 @@ package body CoveragePkg is end if ; end if ; end loop CovLoop ; - write(buf, "%%Error GetHoleBinVal did not find hole. " & - "HoleCount = " & integer'image(HoleCount) & - "ReqHoleNum = " & integer'image(ReqHoleNum) & LF) ; - writeline(OUTPUT, buf) ; + Alert(AlertLogIDVar, GetNamePlus(prefix => "in ", suffix => ", ") & "CoveragePkg.GetHoleBinVal:" & + " did not find hole. HoleCount = " & integer'image(HoleCount) & + "ReqHoleNum = " & integer'image(ReqHoleNum), ERROR + ) ; return CovBinPtr(NumBins).BinVal.all ; end function GetHoleBinVal ; @@ -3375,13 +4056,18 @@ package body CoveragePkg is procedure WriteCovHoles ( file f : text; AtLeast : integer ) is ------------------------------------------------------------ -- variable minAtLeast : integer ; - variable buf : line ; + variable buf : line ; begin WriteBinName(f, "WriteCovHoles: ") ; if NumBins < 1 then - swrite(buf, "%%FATAL, Coverage Model is empty. Nothing to print.") ; - writeline(f, buf) ; - report "Coverage model is empty. Nothing to print." severity failure ; + if WriteBinFileInit or UsingLocalFile then + -- Duplicate Alert in specified file + swrite(buf, "%% Alert FAILURE " & GetNamePlus(prefix => "in ", suffix => ", ") & "CoveragePkg.WriteCovHoles:" & + " coverage model is empty. Nothing to print.") ; + writeline(f, buf) ; + end if ; + Alert(AlertLogIDVar, GetNamePlus(prefix => "in ", suffix => ", ") & "CoveragePkg.WriteCovHoles:" & + " coverage model is empty. Nothing to print.", FAILURE) ; end if ; CovLoop : for i in 1 to NumBins loop -- minAtLeast := minimum(AtLeast,CovBinPtr(i).AtLeast) ; @@ -3398,7 +4084,7 @@ package body CoveragePkg is writeline(f, buf) ; end if ; end loop CovLoop ; - swrite(buf, "") ; + swrite(buf, "") ; writeline(f, buf) ; end procedure WriteCovHoles ; @@ -3409,13 +4095,33 @@ package body CoveragePkg is ------------------------------------------------------------ begin if WriteBinFileInit then + -- Write to Local WriteBinFile - Deprecated, recommend use TranscriptFile instead WriteCovHoles(WriteBinFile, AtLeast) ; + elsif IsTranscriptEnabled then + -- Write to TranscriptFile + WriteCovHoles(TranscriptFile, AtLeast) ; + if IsTranscriptMirrored then + -- Mirrored to OUTPUT + WriteCovHoles(OUTPUT, AtLeast) ; + end if ; else + -- Default Write to OUTPUT WriteCovHoles(OUTPUT, AtLeast) ; end if; end procedure WriteCovHoles ; + ------------------------------------------------------------ + -- Deprecated. New versions use PercentCov. + procedure WriteCovHoles ( LogLevel : LogType ; AtLeast : integer ) is + ------------------------------------------------------------ + begin + if IsLogEnabled(AlertLogIDVar, LogLevel) then + WriteCovHoles(AtLeast) ; + end if; + end procedure WriteCovHoles ; + + ------------------------------------------------------------ -- Deprecated. New versions use PercentCov. procedure WriteCovHoles ( FileName : string; AtLeast : integer ; OpenKind : File_Open_Kind := APPEND_MODE ) is @@ -3425,8 +4131,72 @@ package body CoveragePkg is WriteCovHoles(CovHoleFile, AtLeast) ; end procedure WriteCovHoles ; + ------------------------------------------------------------ + -- Deprecated. New versions use PercentCov. + procedure WriteCovHoles ( LogLevel : LogType ; FileName : string; AtLeast : integer ; OpenKind : File_Open_Kind := APPEND_MODE ) is + ------------------------------------------------------------ + begin + if IsLogEnabled(AlertLogIDVar, LogLevel) then + WriteCovHoles(FileName, AtLeast, OpenKind) ; + end if; + end procedure WriteCovHoles ; + + ------------------------------------------------------------ + -- Deprecated. Use AddCross Instead. + procedure AddBins (CovBin : CovMatrix2Type ; Name : String := "") is + ------------------------------------------------------------ + begin + AddCross(CovBin, Name) ; + end procedure AddBins ; + ------------------------------------------------------------ + procedure AddBins (CovBin : CovMatrix3Type ; Name : String := "") is + ------------------------------------------------------------ + begin + AddCross(CovBin, Name) ; + end procedure AddBins ; + ------------------------------------------------------------ + procedure AddBins (CovBin : CovMatrix4Type ; Name : String := "") is + ------------------------------------------------------------ + begin + AddCross(CovBin, Name) ; + end procedure AddBins ; + + ------------------------------------------------------------ + procedure AddBins (CovBin : CovMatrix5Type ; Name : String := "") is + ------------------------------------------------------------ + begin + AddCross(CovBin, Name) ; + end procedure AddBins ; + + ------------------------------------------------------------ + procedure AddBins (CovBin : CovMatrix6Type ; Name : String := "") is + ------------------------------------------------------------ + begin + AddCross(CovBin, Name) ; + end procedure AddBins ; + + ------------------------------------------------------------ + procedure AddBins (CovBin : CovMatrix7Type ; Name : String := "") is + ------------------------------------------------------------ + begin + AddCross(CovBin, Name) ; + end procedure AddBins ; + + ------------------------------------------------------------ + procedure AddBins (CovBin : CovMatrix8Type ; Name : String := "") is + ------------------------------------------------------------ + begin + AddCross(CovBin, Name) ; + end procedure AddBins ; + + ------------------------------------------------------------ + procedure AddBins (CovBin : CovMatrix9Type ; Name : String := "") is + ------------------------------------------------------------ + begin + AddCross(CovBin, Name) ; + end procedure AddBins ; end protected body CovPType ; @@ -3446,15 +4216,18 @@ package body CoveragePkg is variable NumBins1, NumBins2 : integer ; variable BinInfo1, BinInfo2 : CovBinBaseType ; variable BinVal1, BinVal2 : RangeArrayType(1 to Bin1.GetBinValLength) ; - variable buf : line ; + variable buf : line ; + variable iAlertLogID : AlertLogIDType ; begin + iAlertLogID := Bin1.GetAlertLogID ; + NumBins1 := Bin1.GetNumBins ; NumBins2 := Bin2.GetNumBins ; if (NumBins1 /= NumBins2) then - write(buf, "Bins have different lengths" & LF) ; - writeline(OUTPUT, buf) ; ErrorCount := ErrorCount + 1 ; + print("CoveragePkg.CompareBins: CoverageModels " & Bin1.GetCovModelName & " and " & Bin2.GetCovModelName & + " have different bin lengths") ; return ; end if ; @@ -3464,31 +4237,51 @@ package body CoveragePkg is BinVal1 := Bin1.GetBinVal(i) ; BinVal2 := Bin2.GetBinVal(i) ; if BinInfo1 /= BinInfo2 or BinVal1 /= BinVal2 then - ErrorCount := ErrorCount + 1 ; write(buf, "%% Bin:" & integer'image(i) & " miscompare." & LF) ; - writeline(OUTPUT, buf) ; + -- writeline(OUTPUT, buf) ; swrite(buf, "%% Bin1: ") ; write(buf, BinVal1) ; write(buf, " Action = " & integer'image(BinInfo1.action)) ; write(buf, " Count = " & integer'image(BinInfo1.count)) ; write(buf, " AtLeast = " & integer'image(BinInfo1.AtLeast)) ; - write(buf, " Weight = " & integer'image(BinInfo1.Weight)) ; - writeline(OUTPUT, buf) ; + write(buf, " Weight = " & integer'image(BinInfo1.Weight) & LF ) ; + -- writeline(OUTPUT, buf) ; swrite(buf, "%% Bin2: ") ; write(buf, BinVal2) ; write(buf, " Action = " & integer'image(BinInfo2.action)) ; write(buf, " Count = " & integer'image(BinInfo2.count)) ; write(buf, " AtLeast = " & integer'image(BinInfo2.AtLeast)) ; - write(buf, " Weight = " & integer'image(BinInfo2.Weight)) ; - writeline(OUTPUT, buf) ; + write(buf, " Weight = " & integer'image(BinInfo2.Weight) & LF ) ; + -- writeline(OUTPUT, buf) ; + ErrorCount := ErrorCount + 1 ; + writeline(buf) ; + -- Alert(iAlertLogID, buf.all, ERROR) ; + -- deallocate(buf) ; end if ; end loop ; end procedure CompareBins ; - + + + ------------------------------------------------------------ + -- Experimental. Intended primarily for development. + procedure CompareBins ( + ------------------------------------------------------------ + variable Bin1 : inout CovPType ; + variable Bin2 : inout CovPType + ) is + variable ErrorCount : integer ; + variable iAlertLogID : AlertLogIDType ; + begin + CompareBins(Bin1, Bin2, ErrorCount) ; + iAlertLogID := Bin1.GetAlertLogID ; + AlertIf(ErrorCount /= 0, "CoveragePkg.CompareBins: CoverageModels " & Bin1.GetCovModelName & " and " & Bin2.GetCovModelName & " are not the same.") ; + end procedure CompareBins ; ------------------------------------------------------------ -- package local, Used by GenBin, IllegalBin, and IgnoreBin function MakeBin( + -- Must be pure to allow initializing coverage models passed as generics. + -- Impure implies the expression is not globally static. ------------------------------------------------------------ Min, Max : integer ; NumBin : integer ; @@ -3498,83 +4291,99 @@ package body CoveragePkg is ) return CovBinType is variable iCovBin : CovBinType(1 to NumBin) ; variable TotalBins : integer ; -- either real or integer - variable rMax, rCurMin, rNextMin, rNumItemsInBin, rRemainingBins : real ; -- must be real + variable rMax, rCurMin, rNumItemsInBin, rRemainingBins : real ; -- must be real + variable iCurMin, iCurMax : integer ; begin if Min > Max then - report "MakeBin (GenBin, IllegalBin, IgnoreBin): Min must be <= Max" - severity failure ; + -- Similar to NULL ranges. Only generate report warning. + report "OSVVM.CoveragePkg.MakeBin (called by GenBin, IllegalBin, or IgnoreBin) MAX > MIN generated NULL_BIN" + severity WARNING ; + -- No Alerts. They make this impure. + -- Alert(OSVVM_ALERTLOG_ID, "CoveragePkg.MakeBin (called by GenBin, IllegalBin, IgnoreBin): Min must be <= Max", WARNING) ; return NULL_BIN ; elsif NumBin <= 0 then - report "MakeBin (GenBin, IllegalBin, IgnoreBin): NumBin must be <= 0" - severity failure ; + -- Similar to NULL ranges. Only generate report warning. + report "OSVVM.CoveragePkg.MakeBin (called by GenBin, IllegalBin, or IgnoreBin) NumBin <= 0 generated NULL_BIN" + severity WARNING ; + -- Alerts make this impure. + -- Alert(OSVVM_ALERTLOG_ID, "CoveragePkg.MakeBin (called by GenBin, IllegalBin, IgnoreBin): NumBin must be <= 0", WARNING) ; return NULL_BIN ; elsif NumBin = 1 then iCovBin(1) := ( - BinVal => (1 => (Min, Max)), - Action => Action, - Count => 0, - Weight => Weight, - AtLeast => AtLeast + BinVal => (1 => (Min, Max)), + Action => Action, + Count => 0, + Weight => Weight, + AtLeast => AtLeast ) ; return iCovBin ; else - rCurMin := real(Min) ; + -- Using type real to work around issues with integer sizing + iCurMin := Min ; + rCurMin := real(iCurMin) ; rMax := real(Max) ; rRemainingBins := (minimum( real(NumBin), rMax - rCurMin + 1.0 )) ; TotalBins := integer(rRemainingBins) ; for i in iCovBin'range loop - exit when rRemainingBins = 0.0 ; - rNumItemsInBin := trunc((rMax - rCurMin + 1.0) / rRemainingBins) ; -- can be too large - rNextMin := rCurMin + rNumItemsInBin ; -- can be 2**31 + rNumItemsInBin := trunc((rMax - rCurMin + 1.0) / rRemainingBins) ; -- Max - Min can be larger than integer range. + iCurMax := iCurMin - integer(-rNumItemsInBin + 1.0) ; -- Keep: the "minus negative" works around a simulator bounds issue found in 2015.06 iCovBin(i) := ( - BinVal => (1 => (integer(rCurMin), integer(rNextMin - 1.0))), - Action => Action, - Count => 0, - Weight => Weight, - AtLeast => AtLeast + BinVal => (1 => (iCurMin, iCurMax)), + Action => Action, + Count => 0, + Weight => Weight, + AtLeast => AtLeast ) ; - rCurMin := rNextMin ; rRemainingBins := rRemainingBins - 1.0 ; + exit when rRemainingBins = 0.0 ; + iCurMin := iCurMax + 1 ; + rCurMin := real(iCurMin) ; end loop ; return iCovBin(1 to TotalBins) ; + end if ; end function MakeBin ; --- Old version with bug --- ------------------------------------------------------------ --- -- package local, Used by GenBin, IllegalBin, and IgnoreBin --- function MakeBin( --- ------------------------------------------------------------ --- Min, Max : integer ; --- NumBin : integer ; --- AtLeast : integer ; --- Weight : integer ; --- Action : integer --- ) return CovBinType is --- constant CheckParms : boolean := failed(Min > Max, "MakeBin (GenBin, IllegalBin, IgnoreBin): Min must be <= Max") ; --- constant CALC_NUM_BINS : integer := minimum(NumBin, Max-Min+1) ; --- variable iCovBin : CovBinType(0 to CALC_NUM_BINS -1) ; --- variable CurMin, NextMin, RemainingBins, NumItemsInBin : integer ; --- begin --- CurMin := Min ; --- for i in iCovBin'range loop --- RemainingBins := CALC_NUM_BINS - i ; --- NumItemsInBin := (Max - CurMin + 1) / RemainingBins ; --- NextMin := CurMin + NumItemsInBin ; --- iCovBin(i) := ( --- BinVal => (1 => (CurMin, NextMin - 1)), --- Action => Action, --- Count => 0, --- Weight => Weight, --- AtLeast => AtLeast --- ) ; --- CurMin := NextMin ; --- end loop ; --- return iCovBin ; --- end function MakeBin ; + + ------------------------------------------------------------ + -- package local, Used by GenBin, IllegalBin, and IgnoreBin + function MakeBin( + ------------------------------------------------------------ + A : integer_vector ; + AtLeast : integer ; + Weight : integer ; + Action : integer + ) return CovBinType is + alias NewA : integer_vector(1 to A'length) is A ; + variable iCovBin : CovBinType(1 to A'length) ; + begin + + if A'length <= 0 then + -- Similar to NULL ranges. Only generate report warning. + report "OSVVM.CoveragePkg.MakeBin (called by GenBin, IllegalBin, or IgnoreBin) integer_vector length <= 0 generated NULL_BIN" + severity WARNING ; + -- Alerts make this impure. + -- Alert(OSVVM_ALERTLOG_ID, "CoveragePkg.MakeBin (GenBin, IllegalBin, IgnoreBin): integer_vector parameter must have values", WARNING) ; + return NULL_BIN ; + + else + for i in NewA'Range loop + iCovBin(i) := ( + BinVal => (i => (NewA(i), NewA(i)) ), + Action => Action, + Count => 0, + Weight => Weight, + AtLeast => AtLeast + ) ; + end loop ; + return iCovBin ; + end if ; + end function MakeBin ; + + ------------------------------------------------------------ function GenBin( ------------------------------------------------------------ @@ -3596,7 +4405,7 @@ package body CoveragePkg is ------------------------------------------------------------ - function GenBin(AtLeast : integer ; Min, Max, NumBin : integer ) return CovBinType is + function GenBin( AtLeast : integer ; Min, Max, NumBin : integer ) return CovBinType is ------------------------------------------------------------ begin return MakeBin( @@ -3629,7 +4438,7 @@ package body CoveragePkg is function GenBin ( Min, Max : integer) return CovBinType is ------------------------------------------------------------ begin - -- default, create a separate CovBin for each value + -- create a separate CovBin for each value -- AtLeast and Weight = 1 (must use longer version to specify) return MakeBin( Min => Min, @@ -3643,10 +4452,10 @@ package body CoveragePkg is ------------------------------------------------------------ - function GenBin ( A : integer) return CovBinType is + function GenBin ( A : integer ) return CovBinType is ------------------------------------------------------------ begin - -- default, create a separate CovBin for each value + -- create a single CovBin for A. -- AtLeast and Weight = 1 (must use longer version to specify) return MakeBin( Min => A, @@ -3659,6 +4468,49 @@ package body CoveragePkg is end function GenBin ; + ------------------------------------------------------------ + function GenBin( + ------------------------------------------------------------ + AtLeast : integer ; + Weight : integer ; + A : integer_vector + ) return CovBinType is + begin + return MakeBin( + A => A, + AtLeast => AtLeast, + Weight => Weight, + Action => COV_COUNT + ) ; + end function GenBin ; + + + ------------------------------------------------------------ + function GenBin ( AtLeast : integer ; A : integer_vector ) return CovBinType is + ------------------------------------------------------------ + begin + return MakeBin( + A => A, + AtLeast => AtLeast, + Weight => 1, + Action => COV_COUNT + ) ; + end function GenBin ; + + + ------------------------------------------------------------ + function GenBin ( A : integer_vector ) return CovBinType is + ------------------------------------------------------------ + begin + return MakeBin( + A => A, + AtLeast => 1, + Weight => 1, + Action => COV_COUNT + ) ; + end function GenBin ; + + ------------------------------------------------------------ function IllegalBin ( Min, Max, NumBin : integer ) return CovBinType is ------------------------------------------------------------ @@ -3704,41 +4556,7 @@ package body CoveragePkg is end function IllegalBin ; - ---------------------------------------------------------- - -- function IgnoreBin ( - ---------------------------------------------------------- - -- AtLeast : integer ; - -- Weight : integer ; - -- Min, Max : integer ; - -- NumBin : integer - -- ) return CovBinType is - -- begin - -- return MakeBin( - -- Min => Min, - -- Max => Max, - -- NumBin => NumBin, - -- AtLeast => AtLeast, - -- Weight => Weight, - -- Action => COV_IGNORE - -- ) ; - -- end function IgnoreBin ; - - - ---------------------------------------------------------- - -- function IgnoreBin (AtLeast : integer ; Min, Max, NumBin : integer) return CovBinType is - ---------------------------------------------------------- - -- begin - -- return MakeBin( - -- Min => Min, - -- Max => Max, - -- NumBin => NumBin, - -- AtLeast => AtLeast, - -- Weight => 0, - -- Action => COV_IGNORE - -- ) ; - -- end function IgnoreBin ; - - +-- IgnoreBin should never have an AtLeast parameter ------------------------------------------------------------ function IgnoreBin (Min, Max, NumBin : integer) return CovBinType is ------------------------------------------------------------ @@ -3785,22 +4603,6 @@ package body CoveragePkg is end function IgnoreBin ; - ------------------------------------------------------------ - function GenBin ( - -- Manual entry format for CovBin within lots of extra parens - ------------------------------------------------------------ - ManualBin : CovBinManualType - ) return CovBinType is - alias imBin : CovBinManualType (1 to ManualBin'length) is ManualBin ; - variable iCovBin : CovBinType(imBin'range) ; - begin - for i in iCovBin'range loop - iCovBin(i) := ( (1 => (imBin(i)(0),imBin(i)(1))), imBin(i)(2), 0, 1, 1) ; - end loop ; - return iCovBin ; - end function GenBin ; - - ------------------------------------------------------------ function GenCross( -- 2 -- Cross existing bins @@ -4159,34 +4961,6 @@ package body CoveragePkg is end function GenCross ; - ------------------------------------------------------------ - procedure increment( signal Count : inout integer ) is - ------------------------------------------------------------ - begin - Count <= Count + 1 ; - end procedure increment ; - - - ------------------------------------------------------------ - procedure increment( signal Count : inout integer ; enable : boolean ) is - ------------------------------------------------------------ - begin - if enable then - Count <= Count + 1 ; - end if ; - end procedure increment ; - - - ------------------------------------------------------------ - procedure increment( signal Count : inout integer ; enable : std_ulogic ) is - ------------------------------------------------------------ - begin - if to_x01(enable) = '1' then - Count <= Count + 1 ; - end if ; - end procedure increment ; - - ------------------------------------------------------------ function to_integer ( B : boolean ) return integer is ------------------------------------------------------------ @@ -4233,5 +5007,38 @@ package body CoveragePkg is end loop ; return result ; end function to_integer_vector ; + + + ------------------------------------------------------------ + ------------------------------------------------------------ +-- Deprecated: These are not part of the coverage model + + ------------------------------------------------------------ + procedure increment( signal Count : inout integer ) is + ------------------------------------------------------------ + begin + Count <= Count + 1 ; + end procedure increment ; + + + ------------------------------------------------------------ + procedure increment( signal Count : inout integer ; enable : boolean ) is + ------------------------------------------------------------ + begin + if enable then + Count <= Count + 1 ; + end if ; + end procedure increment ; + + + ------------------------------------------------------------ + procedure increment( signal Count : inout integer ; enable : std_ulogic ) is + ------------------------------------------------------------ + begin + if to_x01(enable) = '1' then + Count <= Count + 1 ; + end if ; + end procedure increment ; + end package body CoveragePkg ; \ No newline at end of file diff --git a/OSVVM/MemoryPkg.vhd b/OSVVM/MemoryPkg.vhd new file mode 100644 index 0000000..cc25e5e --- /dev/null +++ b/OSVVM/MemoryPkg.vhd @@ -0,0 +1,672 @@ +-- +-- File Name: MemoryPkg.vhd +-- Design Unit Name: MemoryPkg +-- Revision: STANDARD VERSION +-- +-- Maintainer: Jim Lewis email: jim@synthworks.com +-- Contributor(s): +-- Jim Lewis email: jim@synthworks.com +-- +-- Description +-- Package defines a protected type, MemoryPType, and methods +-- for efficiently implementing memory data structures +-- +-- Developed for: +-- SynthWorks Design Inc. +-- VHDL Training Classes +-- 11898 SW 128th Ave. Tigard, Or 97223 +-- http://www.SynthWorks.com +-- +-- Revision History: +-- Date Version Description +-- 05/2005: 0.1 Initial revision +-- 06/2015: 2015.06 Updated for Alerts, ... +-- Numerous revisions for VHDL Testbenches and Verification +-- 01/2016: 2016.01 Update for buf.all(buf'left) +-- 11/2016: 2016.11 Refinement to MemRead to return value, X (if X), U (if not initialized) +-- +-- +-- Copyright (c) 2005 - 2016 by SynthWorks Design Inc. All rights reserved. +-- +-- Verbatim copies of this source file may be used and +-- distributed without restriction. +-- +-- This source file is free software; you can redistribute it +-- and/or modify it under the terms of the ARTISTIC License +-- as published by The Perl Foundation; either version 2.0 of +-- the License, or (at your option) any later version. +-- +-- This source is distributed in the hope that it will be +-- useful, but WITHOUT ANY WARRANTY; without even the implied +-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +-- PURPOSE. See the Artistic License for details. +-- +-- You should have received a copy of the license with this source. +-- If not download it from, +-- http://www.perlfoundation.org/artistic_license_2_0 +-- +use std.textio.all ; +library IEEE ; + use IEEE.std_logic_1164.all ; + use IEEE.numeric_std.all ; + use IEEE.numeric_std_unsigned.all ; + use IEEE.math_real.all ; + +use work.TextUtilPkg.all ; +use work.TranscriptPkg.all ; +use work.AlertLogPkg.all ; + +package MemoryPkg is + type MemoryPType is protected + ------------------------------------------------------------ + procedure MemInit ( AddrWidth, DataWidth : in integer ) ; + + ------------------------------------------------------------ + procedure MemWrite ( Addr, Data : in std_logic_vector ) ; + + ------------------------------------------------------------ + procedure MemRead ( + Addr : in std_logic_vector ; + Data : out std_logic_vector + ) ; + impure function MemRead ( Addr : std_logic_vector ) return std_logic_vector ; + + ------------------------------------------------------------ + procedure MemErase ; + procedure deallocate ; + + ------------------------------------------------------------ + procedure SetAlertLogID (A : AlertLogIDType) ; + procedure SetAlertLogID (Name : string ; ParentID : AlertLogIDType := ALERTLOG_BASE_ID ; CreateHierarchy : Boolean := TRUE) ; + impure function GetAlertLogID return AlertLogIDType ; + + ------------------------------------------------------------ + procedure FileReadH ( -- Hexadecimal File Read + FileName : string ; + StartAddr : std_logic_vector ; + EndAddr : std_logic_vector + ) ; + procedure FileReadH (FileName : string ; StartAddr : std_logic_vector) ; + procedure FileReadH (FileName : string) ; + + ------------------------------------------------------------ + procedure FileReadB ( -- Binary File Read + FileName : string ; + StartAddr : std_logic_vector ; + EndAddr : std_logic_vector + ) ; + procedure FileReadB (FileName : string ; StartAddr : std_logic_vector) ; + procedure FileReadB (FileName : string) ; + + ------------------------------------------------------------ + procedure FileWriteH ( -- Hexadecimal File Write + FileName : string ; + StartAddr : std_logic_vector ; + EndAddr : std_logic_vector + ) ; + procedure FileWriteH (FileName : string ; StartAddr : std_logic_vector) ; + procedure FileWriteH (FileName : string) ; + + ------------------------------------------------------------ + procedure FileWriteB ( -- Binary File Write + FileName : string ; + StartAddr : std_logic_vector ; + EndAddr : std_logic_vector + ) ; + procedure FileWriteB (FileName : string ; StartAddr : std_logic_vector) ; + procedure FileWriteB (FileName : string) ; + + end protected MemoryPType ; + +end MemoryPkg ; + +package body MemoryPkg is + constant BLOCK_WIDTH : integer := 10 ; + + type MemoryPType is protected body + + type MemBlockType is array (integer range <>) of integer ; + type MemBlockPtrType is access MemBlockType ; + type MemArrayType is array (integer range <>) of MemBlockPtrType ; + type ArrayPtrVarType is access MemArrayType ; + + variable ArrayPtrVar : ArrayPtrVarType := NULL ; + variable AddrWidthVar : integer := -1 ; -- set by MemInit - merges addr length and initialized checks. + variable DataWidthVar : natural := 1 ; -- set by MemInit + variable BlockkWidthVar : natural := 0 ; -- set by MemInit + + variable AlertLogIDVar : AlertLogIDType := OSVVM_ALERTLOG_ID ; + + type FileFormatType is (BINARY, HEX) ; + + ------------------------------------------------------------ + procedure MemInit ( AddrWidth, DataWidth : In integer ) is + ------------------------------------------------------------ + begin + if AddrWidth <= 0 then + Alert(AlertLogIDVar, "MemoryPType.MemInit. AddrWidth = " & to_string(AddrWidth) & " must be > 0.", FAILURE) ; + return ; + end if ; + if DataWidth <= 0 then + Alert(AlertLogIDVar, "MemoryPType.MemInit. DataWidth = " & to_string(DataWidth) & " must be > 0.", FAILURE) ; + return ; + end if ; + + AddrWidthVar := AddrWidth ; + DataWidthVar := DataWidth ; + BlockkWidthVar := minimum(BLOCK_WIDTH, AddrWidth) ; + ArrayPtrVar := new MemArrayType(0 to 2**(AddrWidth-BlockkWidthVar)-1) ; + end procedure MemInit ; + + ------------------------------------------------------------ + procedure MemWrite ( Addr, Data : in std_logic_vector ) is + ------------------------------------------------------------ + variable BlockAddr, WordAddr : integer ; + alias aAddr : std_logic_vector (Addr'length-1 downto 0) is Addr ; + begin + + -- Check Bounds of Address and if memory is initialized + if Addr'length /= AddrWidthVar then + if (ArrayPtrVar = NULL) then + Alert(AlertLogIDVar, "MemoryPType.MemWrite: Memory not initialized, Write Ignored.", FAILURE) ; + else + Alert(AlertLogIDVar, "MemoryPType.MemWrite: Addr'length: " & to_string(Addr'length) & " /= Memory Address Width: " & to_string(AddrWidthVar), FAILURE) ; + end if ; + return ; + end if ; + + -- Check Bounds on Data + if Data'length /= DataWidthVar then + Alert(AlertLogIDVar, "MemoryPType.MemWrite: Data'length: " & to_string(Data'length) & " /= Memory Data Width: " & to_string(DataWidthVar), FAILURE) ; + return ; + end if ; + + if is_X( Addr ) then + Alert(AlertLogIDVar, "MemoryPType.MemWrite: Address X, Write Ignored.") ; + return ; + end if ; + + -- Slice out upper address to form block address + if aAddr'high >= BlockkWidthVar then + BlockAddr := to_integer(aAddr(aAddr'high downto BlockkWidthVar)) ; + else + BlockAddr := 0 ; + end if ; + + -- If empty, allocate a memory block + if (ArrayPtrVar(BlockAddr) = NULL) then + ArrayPtrVar(BlockAddr) := new MemBlockType(0 to 2**BlockkWidthVar-1) ; + end if ; + + -- Address of a word within a block + WordAddr := to_integer(aAddr(BlockkWidthVar -1 downto 0)) ; + + -- Write to BlockAddr, WordAddr + if (Is_X(Data)) then + ArrayPtrVar(BlockAddr)(WordAddr) := -1 ; + else + ArrayPtrVar(BlockAddr)(WordAddr) := to_integer( Data ) ; + end if ; + end procedure MemWrite ; + + ------------------------------------------------------------ + procedure MemRead ( + ------------------------------------------------------------ + Addr : In std_logic_vector ; + Data : Out std_logic_vector + ) is + variable BlockAddr, WordAddr : integer ; + alias aAddr : std_logic_vector (Addr'length-1 downto 0) is Addr ; + begin + -- Check Bounds of Address and if memory is initialized + if Addr'length /= AddrWidthVar then + if (ArrayPtrVar = NULL) then + Alert(AlertLogIDVar, "MemoryPType.MemRead: Memory not initialized. Returning U", FAILURE) ; + else + Alert(AlertLogIDVar, "MemoryPType.MemRead: Addr'length: " & to_string(Addr'length) & " /= Memory Address Width: " & to_string(AddrWidthVar), FAILURE) ; + end if ; + Data := (Data'range => 'U') ; + return ; + end if ; + + -- Check Bounds on Data + if Data'length /= DataWidthVar then + Alert(AlertLogIDVar, "MemoryPType.MemRead: Data'length: " & to_string(Data'length) & " /= Memory Data Width: " & to_string(DataWidthVar), FAILURE) ; + Data := (Data'range => 'U') ; + return ; + end if ; + + -- If Addr X, data = X + if is_X( aAddr ) then + Data := (Data'range => 'X') ; + return ; + end if ; + + -- Slice out upper address to form block address + if aAddr'high >= BlockkWidthVar then + BlockAddr := to_integer(aAddr(aAddr'high downto BlockkWidthVar)) ; + else + BlockAddr := 0 ; + end if ; + + -- Empty Block, return all U + if (ArrayPtrVar(BlockAddr) = NULL) then + Data := (Data'range => 'U') ; + return ; + end if ; + + -- Address of a word within a block + WordAddr := to_integer(aAddr(BlockkWidthVar -1 downto 0)) ; + + if ArrayPtrVar(BlockAddr)(WordAddr) >= 0 then + -- Get the Word from the Array + Data := to_slv(ArrayPtrVar(BlockAddr)(WordAddr), Data'length) ; + + elsif ArrayPtrVar(BlockAddr)(WordAddr) = -1 then + -- X in Word, return all X + Data := (Data'range => 'X') ; + + else + -- Location Uninitialized, return all X + Data := (Data'range => 'U') ; + + end if ; + end procedure MemRead ; + + ------------------------------------------------------------ + impure function MemRead ( Addr : std_logic_vector ) return std_logic_vector is + ------------------------------------------------------------ + variable BlockAddr, WordAddr : integer ; + alias aAddr : std_logic_vector (Addr'length-1 downto 0) is Addr ; + variable Data : std_logic_vector(DataWidthVar-1 downto 0) ; + begin + MemRead(Addr, Data) ; + return Data ; + end function MemRead ; + + ------------------------------------------------------------ + procedure MemErase is + -- Deallocate the memory, but not the array of pointers + ------------------------------------------------------------ + begin + for BlockAddr in ArrayPtrVar'range loop + if (ArrayPtrVar(BlockAddr) /= NULL) then + deallocate (ArrayPtrVar(BlockAddr)) ; + end if ; + end loop ; + end procedure ; + + ------------------------------------------------------------ + procedure deallocate is + -- Deallocate all allocated memory + ------------------------------------------------------------ + begin + MemErase ; + deallocate(ArrayPtrVar) ; + AddrWidthVar := -1 ; + DataWidthVar := 1 ; + BlockkWidthVar := 0 ; + end procedure ; + + ------------------------------------------------------------ + procedure SetAlertLogID (A : AlertLogIDType) is + ------------------------------------------------------------ + begin + AlertLogIDVar := A ; + end procedure SetAlertLogID ; + + ------------------------------------------------------------ + procedure SetAlertLogID(Name : string ; ParentID : AlertLogIDType := ALERTLOG_BASE_ID ; CreateHierarchy : Boolean := TRUE) is + ------------------------------------------------------------ + begin + AlertLogIDVar := GetAlertLogID(Name, ParentID, CreateHierarchy) ; + end procedure SetAlertLogID ; + + ------------------------------------------------------------ + impure function GetAlertLogID return AlertLogIDType is + ------------------------------------------------------------ + begin + return AlertLogIDVar ; + end function GetAlertLogID ; + + ------------------------------------------------------------ + -- PT Local + procedure FileReadX ( + -- Hexadecimal or Binary File Read + ------------------------------------------------------------ + FileName : string ; + DataFormat : FileFormatType ; + StartAddr : std_logic_vector ; + EndAddr : std_logic_vector + ) is + -- Format: + -- @hh..h -- Address in hex + -- hhh_XX_ZZ -- data values in hex - space delimited + -- "--" or "//" -- comments + file MemFile : text open READ_MODE is FileName ; + + variable Addr : std_logic_vector(AddrWidthVar - 1 downto 0) ; + variable SmallAddr : std_logic_vector(AddrWidthVar - 1 downto 0) ; + variable BigAddr : std_logic_vector(AddrWidthVar - 1 downto 0) ; + variable Data : std_logic_vector(DataWidthVar - 1 downto 0) ; + variable LineNum : natural ; + variable ItemNum : natural ; + variable AddrInc : std_logic_vector(AddrWidthVar - 1 downto 0) ; + variable buf : line ; + variable ReadValid : boolean ; + variable Empty : boolean ; + variable MultiLineComment : boolean ; + variable NextChar : character ; + variable StrLen : integer ; + begin + MultiLineComment := FALSE ; + if StartAddr'length /= AddrWidthVar and EndAddr'length /= AddrWidthVar then + if (ArrayPtrVar = NULL) then + Alert(AlertLogIDVar, "MemoryPType.FileReadX: Memory not initialized, FileRead Ignored.", FAILURE) ; + else + Alert(AlertLogIDVar, "MemoryPType.FileReadX: Addr'length: " & to_string(Addr'length) & " /= Memory Address Width: " & to_string(AddrWidthVar), FAILURE) ; + end if ; + return ; + end if ; + + Addr := StartAddr ; + LineNum := 0 ; + + if StartAddr <= EndAddr then + SmallAddr := StartAddr ; + BigAddr := EndAddr ; + AddrInc := (AddrWidthVar -1 downto 0 => '0') + 1 ; + else + SmallAddr := EndAddr ; + BigAddr := StartAddr ; + AddrInc := (others => '1') ; -- -1 + end if; + + ReadLineLoop : while not EndFile(MemFile) loop + ReadLine(MemFile, buf) ; + LineNum := LineNum + 1 ; + ItemNum := 0 ; + + ItemLoop : loop + EmptyOrCommentLine(buf, Empty, MultiLineComment) ; + exit ItemLoop when Empty ; + ItemNum := ItemNum + 1 ; + NextChar := buf.all(buf'left) ; + + if (NextChar = '@') then + -- Get Address + read(buf, NextChar) ; + ReadHexToken(buf, Addr, StrLen) ; + exit ReadLineLoop when AlertIf(AlertLogIDVar, StrLen = 0, "MemoryPType.FileReadX: Address length 0 on line: " & to_string(LineNum), FAILURE) ; + exit ItemLoop when AlertIf(AlertLogIDVar, Addr < SmallAddr, + "MemoryPType.FileReadX: Address in file: " & to_hstring(Addr) & + " < StartAddr: " & to_hstring(StartAddr) & " on line: " & to_string(LineNum)) ; + exit ItemLoop when AlertIf(AlertLogIDVar, Addr > BigAddr, + "MemoryPType.FileReadX: Address in file: " & to_hstring(Addr) & + " > EndAddr: " & to_hstring(BigAddr) & " on line: " & to_string(LineNum)) ; + + elsif DataFormat = HEX and ishex(NextChar) then + -- Get Hex Data + ReadHexToken(buf, data, StrLen) ; + exit ReadLineLoop when AlertIfNot(AlertLogIDVar, StrLen > 0, + "MemoryPType.FileReadH: Error while reading data on line: " & to_string(LineNum) & + " Item number: " & to_string(ItemNum), FAILURE) ; + log("MemoryPType.FileReadX: MemWrite(Addr => " & to_hstring(Addr) & ", Data => " & to_hstring(Data) & ")", DEBUG) ; + MemWrite(Addr, data) ; + Addr := Addr + AddrInc ; + + elsif DataFormat = BINARY and isstd_logic(NextChar) then + -- Get Binary Data + -- read(buf, data, ReadValid) ; + ReadBinaryToken(buf, data, StrLen) ; + -- exit ReadLineLoop when AlertIfNot(AlertLogIDVar, ReadValid, + exit ReadLineLoop when AlertIfNot(AlertLogIDVar, StrLen > 0, + "MemoryPType.FileReadB: Error while reading data on line: " & to_string(LineNum) & + " Item number: " & to_string(ItemNum), FAILURE) ; + log("MemoryPType.FileReadX: MemWrite(Addr => " & to_hstring(Addr) & ", Data => " & to_string(Data) & ")", DEBUG) ; + MemWrite(Addr, data) ; + Addr := Addr + AddrInc ; + + else + -- Invalid Text, Issue Warning and skip it + Alert(AlertLogIDVar, + "MemoryPType.FileReadX: Invalid text on line: " & to_string(LineNum) & + " Item: " & to_string(ItemNum) & ". Skipping text: " & buf.all) ; + exit ItemLoop ; + end if ; + + end loop ItemLoop ; + end loop ReadLineLoop ; + +-- -- must read EndAddr-StartAddr number of words if both start and end specified +-- if (StartAddr /= 0 or (not EndAddr) /= 0) and (Addr /= EndAddr) then +-- Alert("MemoryPType.FileReadH: insufficient data values", WARNING) ; +-- end if ; + file_close(MemFile) ; + end FileReadX ; + + ------------------------------------------------------------ + procedure FileReadH ( + -- Hexadecimal File Read + ------------------------------------------------------------ + FileName : string ; + StartAddr : std_logic_vector ; + EndAddr : std_logic_vector + ) is + begin + FileReadX(FileName, HEX, StartAddr, EndAddr) ; + end FileReadH ; + + ------------------------------------------------------------ + procedure FileReadH (FileName : string ; StartAddr : std_logic_vector) is + -- Hexadecimal File Read + ------------------------------------------------------------ + constant EndAddr : std_logic_vector(AddrWidthVar - 1 downto 0) := (others => '1') ; + begin + FileReadX(FileName, HEX, StartAddr, EndAddr) ; + end FileReadH ; + + ------------------------------------------------------------ + procedure FileReadH (FileName : string) is + -- Hexadecimal File Read + ------------------------------------------------------------ + constant StartAddr : std_logic_vector(AddrWidthVar - 1 downto 0) := (others => '0') ; + constant EndAddr : std_logic_vector(AddrWidthVar - 1 downto 0) := (others => '1') ; + begin + FileReadX(FileName, HEX, StartAddr, EndAddr) ; + end FileReadH ; + + ------------------------------------------------------------ + procedure FileReadB ( + -- Binary File Read + ------------------------------------------------------------ + FileName : string ; + StartAddr : std_logic_vector ; + EndAddr : std_logic_vector + ) is + begin + FileReadX(FileName, BINARY, StartAddr, EndAddr) ; + end FileReadB ; + + ------------------------------------------------------------ + procedure FileReadB (FileName : string ; StartAddr : std_logic_vector) is + -- Binary File Read + ------------------------------------------------------------ + constant EndAddr : std_logic_vector(AddrWidthVar - 1 downto 0) := (others => '1') ; + begin + FileReadX(FileName, BINARY, StartAddr, EndAddr) ; + end FileReadB ; + + ------------------------------------------------------------ + procedure FileReadB (FileName : string) is + -- Binary File Read + ------------------------------------------------------------ + constant StartAddr : std_logic_vector(AddrWidthVar - 1 downto 0) := (others => '0') ; + constant EndAddr : std_logic_vector(AddrWidthVar - 1 downto 0) := (others => '1') ; + begin + FileReadX(FileName, BINARY, StartAddr, EndAddr) ; + end FileReadB ; + + ------------------------------------------------------------ + -- PT Local + procedure FileWriteX ( + -- Hexadecimal or Binary File Write + ------------------------------------------------------------ + FileName : string ; + DataFormat : FileFormatType ; + StartAddr : std_logic_vector ; + EndAddr : std_logic_vector + ) is + -- Format: + -- @hh..h -- Address in hex + -- hhhhh -- data one per line in either hex or binary as specified + file MemFile : text open WRITE_MODE is FileName ; + alias normStartAddr : std_logic_vector(StartAddr'length-1 downto 0) is StartAddr ; + alias normEndAddr : std_logic_vector(EndAddr'length-1 downto 0) is EndAddr ; + variable StartBlockAddr : natural ; + variable EndBlockAddr : natural ; + variable StartWordAddr : natural ; + variable EndWordAddr : natural ; + variable Data : std_logic_vector(DataWidthVar - 1 downto 0) ; + variable FoundData : boolean ; + variable buf : line ; + begin + if StartAddr'length /= AddrWidthVar and EndAddr'length /= AddrWidthVar then + -- Check StartAddr and EndAddr Widths and Memory not initialized + if (ArrayPtrVar = NULL) then + Alert(AlertLogIDVar, "MemoryPType.FileWriteX: Memory not initialized, FileRead Ignored.", FAILURE) ; + else + AlertIf(AlertLogIDVar, StartAddr'length /= AddrWidthVar, "MemoryPType.FileWriteX: StartAddr'length: " + & to_string(StartAddr'length) & + " /= Memory Address Width: " & to_string(AddrWidthVar), FAILURE) ; + AlertIf(AlertLogIDVar, EndAddr'length /= AddrWidthVar, "MemoryPType.FileWriteX: EndAddr'length: " + & to_string(EndAddr'length) & + " /= Memory Address Width: " & to_string(AddrWidthVar), FAILURE) ; + end if ; + return ; + end if ; + + if StartAddr > EndAddr then + -- Only support ascending addresses + Alert(AlertLogIDVar, "MemoryPType.FileWriteX: StartAddr: " & to_hstring(StartAddr) & + " > EndAddr: " & to_hstring(EndAddr), FAILURE) ; + return ; + end if ; + + -- Slice out upper address to form block address + if AddrWidthVar >= BlockkWidthVar then + StartBlockAddr := to_integer(normStartAddr(AddrWidthVar-1 downto BlockkWidthVar)) ; + EndBlockAddr := to_integer( normEndAddr(AddrWidthVar-1 downto BlockkWidthVar)) ; + else + StartBlockAddr := 0 ; + EndBlockAddr := 0 ; + end if ; + + BlockAddrLoop : for BlockAddr in StartBlockAddr to EndBlockAddr loop + next BlockAddrLoop when ArrayPtrVar(BlockAddr) = NULL ; + if BlockAddr = StartBlockAddr then + StartWordAddr := to_integer(normStartAddr(BlockkWidthVar-1 downto 0)) ; + else + StartWordAddr := 0 ; + end if ; + if BlockAddr = EndBlockAddr then + EndWordAddr := to_integer(normEndAddr(BlockkWidthVar-1 downto 0)) ; + else + EndWordAddr := 2**BlockkWidthVar-1 ; + end if ; + FoundData := FALSE ; + WordAddrLoop : for WordAddr in StartWordAddr to EndWordAddr loop + if (ArrayPtrVar(BlockAddr)(WordAddr) < 0) then + -- X in Word, return all X + Data := (Data'range => 'X') ; + FoundData := FALSE ; + else + -- Get the Word from the Array + Data := to_slv(ArrayPtrVar(BlockAddr)(WordAddr), Data'length) ; + if not FoundData then + -- Write Address + write(buf, '@') ; + hwrite(buf, to_slv(BlockAddr, AddrWidthVar-BlockkWidthVar) & to_slv(WordAddr, BlockkWidthVar)) ; + writeline(MemFile, buf) ; + end if ; + FoundData := TRUE ; + end if ; + if FoundData then -- Write Data + if DataFormat = HEX then + hwrite(buf, Data) ; + writeline(MemFile, buf) ; + else + write(buf, Data) ; + writeline(MemFile, buf) ; + end if; + end if ; + end loop WordAddrLoop ; + end loop BlockAddrLoop ; + file_close(MemFile) ; + end FileWriteX ; + + ------------------------------------------------------------ + procedure FileWriteH ( + -- Hexadecimal File Write + ------------------------------------------------------------ + FileName : string ; + StartAddr : std_logic_vector ; + EndAddr : std_logic_vector + ) is + begin + FileWriteX(FileName, HEX, StartAddr, EndAddr) ; + end FileWriteH ; + + ------------------------------------------------------------ + procedure FileWriteH (FileName : string ; StartAddr : std_logic_vector) is + -- Hexadecimal File Write + ------------------------------------------------------------ + constant EndAddr : std_logic_vector(AddrWidthVar - 1 downto 0) := (others => '1') ; + begin + FileWriteX(FileName, HEX, StartAddr, EndAddr) ; + end FileWriteH ; + + ------------------------------------------------------------ + procedure FileWriteH (FileName : string) is + -- Hexadecimal File Write + ------------------------------------------------------------ + constant StartAddr : std_logic_vector(AddrWidthVar - 1 downto 0) := (others => '0') ; + constant EndAddr : std_logic_vector(AddrWidthVar - 1 downto 0) := (others => '1') ; + begin + FileWriteX(FileName, HEX, StartAddr, EndAddr) ; + end FileWriteH ; + + ------------------------------------------------------------ + procedure FileWriteB ( + -- Binary File Write + ------------------------------------------------------------ + FileName : string ; + StartAddr : std_logic_vector ; + EndAddr : std_logic_vector + ) is + begin + FileWriteX(FileName, BINARY, StartAddr, EndAddr) ; + end FileWriteB ; + + ------------------------------------------------------------ + procedure FileWriteB (FileName : string ; StartAddr : std_logic_vector) is + -- Binary File Write + ------------------------------------------------------------ + constant EndAddr : std_logic_vector(AddrWidthVar - 1 downto 0) := (others => '1') ; + begin + FileWriteX(FileName, BINARY, StartAddr, EndAddr) ; + end FileWriteB ; + + ------------------------------------------------------------ + procedure FileWriteB (FileName : string) is + -- Binary File Write + ------------------------------------------------------------ + constant StartAddr : std_logic_vector(AddrWidthVar - 1 downto 0) := (others => '0') ; + constant EndAddr : std_logic_vector(AddrWidthVar - 1 downto 0) := (others => '1') ; + begin + FileWriteX(FileName, BINARY, StartAddr, EndAddr) ; + end FileWriteB ; + + end protected body MemoryPType ; + +end MemoryPkg ; \ No newline at end of file diff --git a/test/OSVVM/MessagePkg.vhd b/OSVVM/MessagePkg.vhd old mode 100755 new mode 100644 similarity index 52% rename from test/OSVVM/MessagePkg.vhd rename to OSVVM/MessagePkg.vhd index 597d5bb..3d442c9 --- a/test/OSVVM/MessagePkg.vhd +++ b/OSVVM/MessagePkg.vhd @@ -1,204 +1,165 @@ --- --- File Name: MessagePkg.vhd --- Design Unit Name: MessagePkg --- Revision: STANDARD VERSION, revision 2014.01 --- --- Maintainer: Jim Lewis email: jim@synthworks.com --- Contributor(s): --- Jim Lewis SynthWorks --- --- --- Package Defines --- Data structure for name and message handling. --- --- Developed for: --- SynthWorks Design Inc. --- VHDL Training Classes --- 11898 SW 128th Ave. Tigard, Or 97223 --- http://www.SynthWorks.com --- --- Latest standard version available at: --- http://www.SynthWorks.com/downloads --- --- Revision History: --- Date Version Description --- 06/2010: 0.1 Initial revision --- --- --- Copyright (c) 2010 - 2013 by SynthWorks Design Inc. All rights reserved. --- --- Verbatim copies of this source file may be used and --- distributed without restriction. --- --- This source file is free software; you can redistribute it --- and/or modify it under the terms of the ARTISTIC License --- as published by The Perl Foundation; either version 2.0 of --- the License, or (at your option) any later version. --- --- This source is distributed in the hope that it will be --- useful, but WITHOUT ANY WARRANTY; without even the implied --- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR --- PURPOSE. See the Artistic License for details. --- --- You should have received a copy of the license with this source. --- If not download it from, --- http://www.perlfoundation.org/artistic_license_2_0 --- - -library ieee ; -use ieee.std_logic_1164.all ; -use ieee.numeric_std.all ; -use ieee.math_real.all ; -use std.textio.all ; - -package MessagePkg is - - type MessagePType is protected - - procedure SetName (NameIn : String) ; - impure function GetName return string ; - impure function IsSetName return boolean ; - - procedure SetMessage (MessageIn : String) ; - impure function GetMessage (ItemNumber : integer) return string ; - impure function GetMessageCount return integer ; - - procedure DeallocateName ; -- clear name - procedure DeallocateMessage ; -- clear message - procedure Deallocate ; -- clear all - - end protected MessagePType ; - -end package MessagePkg ; -package body MessagePkg is - - -- Local Data Structure Types - type LineArrayType is array (natural range <>) of line ; - type LineArrayPtrType is access LineArrayType ; - - ------------------------------------------------------------ - -- Local. Get first word from a string - function GetWord (Message : string) return string is - ------------------------------------------------------------ - alias aMessage : string( 1 to Message'length) is Message ; - begin - for i in aMessage'range loop - if aMessage(i) = ' ' or aMessage(i) = HT then - return aMessage(1 to i-1) ; - end if ; - end loop ; - return aMessage ; - end function GetWord ; - - - type MessagePType is protected body - - variable NamePtr : line := new string'("") ; - variable MessageCount : integer := 0 ; - constant INITIAL_ITEM_COUNT : integer := 25 ; - variable MaxMessageCount : integer := INITIAL_ITEM_COUNT ; - variable MessagePtr : LineArrayPtrType := new LineArrayType(1 to INITIAL_ITEM_COUNT) ; - - ------------------------------------------------------------ - procedure SetName (NameIn : String) is - ------------------------------------------------------------ - begin - deallocate(NamePtr) ; - NamePtr := new string'(NameIn) ; - end procedure SetName ; - - ------------------------------------------------------------ - impure function GetName return string is - ------------------------------------------------------------ - begin - if NamePtr.all /= "" or MessagePtr(1) = NULL then - return NamePtr.all ; - else - return GetWord( MessagePtr(1).all ) ; - end if ; - end function GetName ; - - ------------------------------------------------------------ - impure function IsSetName return boolean is - ------------------------------------------------------------ - begin - return NamePtr.all /= "" ; - end function IsSetName ; - - ------------------------------------------------------------ - procedure SetMessage (MessageIn : String) is - ------------------------------------------------------------ - variable NamePtr : line ; - variable OldMaxMessageCount : integer ; - variable OldMessagePtr : LineArrayPtrType ; - begin - MessageCount := MessageCount + 1 ; - if MessageCount > MaxMessageCount then - OldMaxMessageCount := MaxMessageCount ; - MaxMessageCount := OldMaxMessageCount * 2 ; - OldMessagePtr := MessagePtr ; - MessagePtr := new LineArrayType(1 to MaxMessageCount) ; - for i in 1 to OldMaxMessageCount loop - MessagePtr(i) := OldMessagePtr(i) ; - end loop ; - Deallocate( OldMessagePtr ) ; - end if ; - MessagePtr(MessageCount) := new string'(MessageIn) ; - end procedure SetMessage ; - - ------------------------------------------------------------ - impure function GetMessage (ItemNumber : integer) return string is - ------------------------------------------------------------ - begin - if MessageCount > 0 then - if ItemNumber >= 1 and ItemNumber <= MessageCount then - return MessagePtr(ItemNumber).all ; - else - report LF & "%% MessagePkg:MessagePType.GetMessage input value out of range" severity failure ; - return "" ; -- error if this happens - end if ; - else - return NamePtr.all ; - end if ; - end function GetMessage ; - - ------------------------------------------------------------ - impure function GetMessageCount return integer is - ------------------------------------------------------------ - begin - return MessageCount ; - end function GetMessageCount ; - - ------------------------------------------------------------ - procedure DeallocateName is -- clear name - ------------------------------------------------------------ - begin - deallocate(NamePtr) ; - NamePtr := new string'("") ; - end procedure DeallocateName ; - - ------------------------------------------------------------ - procedure DeallocateMessage is -- clear message - ------------------------------------------------------------ - variable CurPtr : LineArrayPtrType ; - begin - for i in 1 to MessageCount loop - deallocate( MessagePtr(i) ) ; - end loop ; - MessageCount := 0 ; - -- Do NOT Do this: deallocate( MessagePtr ) ; - end procedure DeallocateMessage ; - - ------------------------------------------------------------ - procedure Deallocate is -- clear all - ------------------------------------------------------------ - begin - DeallocateName ; - DeallocateMessage ; - end procedure Deallocate ; - - end protected body MessagePType ; - -end package body MessagePkg ; - - +-- +-- File Name: MessagePkg.vhd +-- Design Unit Name: MessagePkg +-- Revision: STANDARD VERSION, revision 2015.01 +-- +-- Maintainer: Jim Lewis email: jim@synthworks.com +-- Contributor(s): +-- Jim Lewis SynthWorks +-- +-- +-- Package Defines +-- Data structure for multi-line name/message to be associated with a data structure. +-- +-- Developed for: +-- SynthWorks Design Inc. +-- VHDL Training Classes +-- 11898 SW 128th Ave. Tigard, Or 97223 +-- http://www.SynthWorks.com +-- +-- Latest standard version available at: +-- http://www.SynthWorks.com/downloads +-- +-- Revision History: +-- Date Version Description +-- 06/2010: 0.1 Initial revision +-- 07/2014: 2014.07 Moved specialization required by CoveragePkg to CoveragePkg +-- 07/2014: 2014.07a Removed initialized pointers which can lead to memory leaks. +-- 01/2015: 2015.01 Removed initialized parameter from Get +-- +-- +-- Copyright (c) 2010 - 2015 by SynthWorks Design Inc. All rights reserved. +-- +-- Verbatim copies of this source file may be used and +-- distributed without restriction. +-- +-- This source file is free software; you can redistribute it +-- and/or modify it under the terms of the ARTISTIC License +-- as published by The Perl Foundation; either version 2.0 of +-- the License, or (at your option) any later version. +-- +-- This source is distributed in the hope that it will be +-- useful, but WITHOUT ANY WARRANTY; without even the implied +-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +-- PURPOSE. See the Artistic License for details. +-- +-- You should have received a copy of the license with this source. +-- If not download it from, +-- http://www.perlfoundation.org/artistic_license_2_0 +-- +use work.OsvvmGlobalPkg.all ; +use work.AlertLogPkg.all ; + +library ieee ; +use ieee.std_logic_1164.all ; +use ieee.numeric_std.all ; +use ieee.math_real.all ; +use std.textio.all ; + +package MessagePkg is + + type MessagePType is protected + + procedure Set (MessageIn : String) ; + impure function Get (ItemNumber : integer) return string ; + impure function GetCount return integer ; + impure function IsSet return boolean ; + procedure Clear ; -- clear message + procedure Deallocate ; -- clear message + + end protected MessagePType ; + +end package MessagePkg ; + +--- /////////////////////////////////////////////////////////////////////////// +--- /////////////////////////////////////////////////////////////////////////// +--- /////////////////////////////////////////////////////////////////////////// + +package body MessagePkg is + + -- Local Data Structure Types + type LineArrayType is array (natural range <>) of line ; + type LineArrayPtrType is access LineArrayType ; + + type MessagePType is protected body + + variable MessageCount : integer := 0 ; + constant INITIAL_ITEM_COUNT : integer := 16 ; + variable MaxMessageCount : integer := 0 ; + variable MessagePtr : LineArrayPtrType ; + + ------------------------------------------------------------ + procedure Set (MessageIn : String) is + ------------------------------------------------------------ + variable NamePtr : line ; + variable OldMaxMessageCount : integer ; + variable OldMessagePtr : LineArrayPtrType ; + begin + MessageCount := MessageCount + 1 ; + if MessageCount > MaxMessageCount then + OldMaxMessageCount := MaxMessageCount ; + MaxMessageCount := MaxMessageCount + INITIAL_ITEM_COUNT ; + OldMessagePtr := MessagePtr ; + MessagePtr := new LineArrayType(1 to MaxMessageCount) ; + for i in 1 to OldMaxMessageCount loop + MessagePtr(i) := OldMessagePtr(i) ; + end loop ; + Deallocate( OldMessagePtr ) ; + end if ; + MessagePtr(MessageCount) := new string'(MessageIn) ; + end procedure Set ; + + ------------------------------------------------------------ + impure function Get (ItemNumber : integer) return string is + ------------------------------------------------------------ + begin + if MessageCount > 0 then + if ItemNumber >= 1 and ItemNumber <= MessageCount then + return MessagePtr(ItemNumber).all ; + else + Alert(OSVVM_ALERTLOG_ID, "%% MessagePkg.Get input value out of range", FAILURE) ; + return "" ; -- error if this happens + end if ; + else + Alert(OSVVM_ALERTLOG_ID, "%% MessagePkg.Get message is not set", FAILURE) ; + return "" ; -- error if this happens + end if ; + end function Get ; + + ------------------------------------------------------------ + impure function GetCount return integer is + ------------------------------------------------------------ + begin + return MessageCount ; + end function GetCount ; + + ------------------------------------------------------------ + impure function IsSet return boolean is + ------------------------------------------------------------ + begin + return MessageCount > 0 ; + end function IsSet ; + + ------------------------------------------------------------ + procedure Deallocate is -- clear message + ------------------------------------------------------------ + variable CurPtr : LineArrayPtrType ; + begin + for i in 1 to MessageCount loop + deallocate( MessagePtr(i) ) ; + end loop ; + MessageCount := 0 ; + MaxMessageCount := 0 ; + deallocate( MessagePtr ) ; + end procedure Deallocate ; + + ------------------------------------------------------------ + procedure Clear is -- clear + ------------------------------------------------------------ + begin + Deallocate ; + end procedure Clear ; + + end protected body MessagePType ; + +end package body MessagePkg ; \ No newline at end of file diff --git a/OSVVM/NamePkg.vhd b/OSVVM/NamePkg.vhd new file mode 100644 index 0000000..44e4ec6 --- /dev/null +++ b/OSVVM/NamePkg.vhd @@ -0,0 +1,129 @@ +-- +-- File Name: NamePkg.vhd +-- Design Unit Name: NamePkg +-- Revision: STANDARD VERSION +-- +-- Maintainer: Jim Lewis email: jim@synthworks.com +-- Contributor(s): +-- Jim Lewis SynthWorks +-- +-- +-- Package Defines +-- Data structure for name. +-- +-- Developed for: +-- SynthWorks Design Inc. +-- VHDL Training Classes +-- 11898 SW 128th Ave. Tigard, Or 97223 +-- http://www.SynthWorks.com +-- +-- Latest standard version available at: +-- http://www.SynthWorks.com/downloads +-- +-- Revision History: +-- Date Version Description +-- 06/2010: 0.1 Initial revision +-- 07/2014: 2014.07 Moved specialization required by CoveragePkg to CoveragePkg +-- Separated name handling from message handling to simplify naming +-- 12/2014: 2014.07a Removed initialized pointers which can lead to memory leaks. +-- 05/2015 2015.06 Added input to Get to return when not initialized +-- +-- +-- Copyright (c) 2010 - 2015 by SynthWorks Design Inc. All rights reserved. +-- +-- Verbatim copies of this source file may be used and +-- distributed without restriction. +-- +-- This source file is free software; you can redistribute it +-- and/or modify it under the terms of the ARTISTIC License +-- as published by The Perl Foundation; either version 2.0 of +-- the License, or (at your option) any later version. +-- +-- This source is distributed in the hope that it will be +-- useful, but WITHOUT ANY WARRANTY; without even the implied +-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +-- PURPOSE. See the Artistic License for details. +-- +-- You should have received a copy of the license with this source. +-- If not download it from, +-- http://www.perlfoundation.org/artistic_license_2_0 +-- + +use std.textio.all ; + +package NamePkg is + + type NamePType is protected + procedure Set (NameIn : String) ; + impure function Get (DefaultName : string := "") return string ; + impure function GetOpt return string ; + impure function IsSet return boolean ; + procedure Clear ; -- clear name + procedure Deallocate ; -- effectively alias to clear name + end protected NamePType ; + +end package NamePkg ; + +--- /////////////////////////////////////////////////////////////////////////// +--- /////////////////////////////////////////////////////////////////////////// +--- /////////////////////////////////////////////////////////////////////////// + +package body NamePkg is + type NamePType is protected body + + variable NamePtr : line ; + + ------------------------------------------------------------ + procedure Set (NameIn : String) is + ------------------------------------------------------------ + begin + deallocate(NamePtr) ; + NamePtr := new string'(NameIn) ; + end procedure Set ; + + ------------------------------------------------------------ + impure function Get (DefaultName : string := "") return string is + ------------------------------------------------------------ + begin + if NamePtr = NULL then + return DefaultName ; + else + return NamePtr.all ; + end if ; + end function Get ; + + ------------------------------------------------------------ + impure function GetOpt return string is + ------------------------------------------------------------ + begin + if NamePtr = NULL then + return NUL & "" ; + else + return NamePtr.all ; + end if ; + end function GetOpt ; + + ------------------------------------------------------------ + impure function IsSet return boolean is + ------------------------------------------------------------ + begin + return NamePtr /= NULL ; + end function IsSet ; + + ------------------------------------------------------------ + procedure Clear is -- clear name + ------------------------------------------------------------ + begin + deallocate(NamePtr) ; + end procedure Clear ; + + ------------------------------------------------------------ + procedure Deallocate is -- clear name + ------------------------------------------------------------ + begin + Clear ; + end procedure Deallocate ; + + end protected body NamePType ; + +end package body NamePkg ; \ No newline at end of file diff --git a/OSVVM/OsvvmContext.vhd b/OSVVM/OsvvmContext.vhd new file mode 100644 index 0000000..14538a2 --- /dev/null +++ b/OSVVM/OsvvmContext.vhd @@ -0,0 +1,63 @@ +-- +-- File Name: OsvvmContext.vhd +-- Design Unit Name: OsvvmContext +-- Revision: STANDARD VERSION +-- +-- Maintainer: Jim Lewis email: jim@synthworks.com-- +-- +-- Description +-- Context Declaration for OSVVM packages +-- +-- Developed by/for: +-- SynthWorks Design Inc. +-- VHDL Training Classes +-- 11898 SW 128th Ave. Tigard, Or 97223 +-- http://www.SynthWorks.com +-- +-- Latest standard version available at: +-- http://www.SynthWorks.com/downloads +-- +-- Revision History: +-- Date Version Description +-- 01/2015 2015.01 Initial Revision +-- 06/2015 2015.06 Added MemoryPkg +-- 11/2016 2016.11 Added TbUtilPkg and ResolutionPkg +-- +-- +-- Copyright (c) 2015 - 2016 by SynthWorks Design Inc. All rights reserved. +-- +-- Verbatim copies of this source file may be used and +-- distributed without restriction. +-- +-- This source file is free software; you can redistribute it +-- and/or modify it under the terms of the ARTISTIC License +-- as published by The Perl Foundation; either version 2.0 of +-- the License, or (at your option) any later version. +-- +-- This source is distributed in the hope that it will be +-- useful, but WITHOUT ANY WARRANTY; without even the implied +-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +-- PURPOSE. See the Artistic License for details. +-- +-- You should have received a copy of the license with this source. +-- If not download it from, +-- http://www.perlfoundation.org/artistic_license_2_0 +-- +-- + +context OsvvmContext is + library OSVVM ; + + use OSVVM.NamePkg.all ; + use OSVVM.TranscriptPkg.all ; + use OSVVM.TextUtilPkg.all ; + use OSVVM.OsvvmGlobalPkg.all ; + use OSVVM.AlertLogPkg.all ; + use OSVVM.RandomPkg.all ; + use OSVVM.CoveragePkg.all ; + use OSVVM.MemoryPkg.all ; + use OSVVM.ResolutionPkg.all ; + use OSVVM.TbUtilPkg.all ; + +end context OsvvmContext ; + diff --git a/OSVVM/OsvvmGlobalPkg.vhd b/OSVVM/OsvvmGlobalPkg.vhd new file mode 100644 index 0000000..1d61e2b --- /dev/null +++ b/OSVVM/OsvvmGlobalPkg.vhd @@ -0,0 +1,350 @@ +-- +-- File Name: OsvvmGlobalPkg.vhd +-- Design Unit Name: OsvvmGlobalPkg +-- Revision: STANDARD VERSION, revision 2015.01 +-- +-- Maintainer: Jim Lewis email: jim@synthworks.com +-- Contributor(s): +-- Jim Lewis jim@synthworks.com +-- +-- +-- Description: +-- Global Settings for OSVVM packages +-- +-- +-- Developed for: +-- SynthWorks Design Inc. +-- VHDL Training Classes +-- 11898 SW 128th Ave. Tigard, Or 97223 +-- http://www.SynthWorks.com +-- +-- Revision History: +-- Date Version Description +-- 01/2014: 2015.01 Initial revision +-- +-- +-- Copyright (c) 2015 by SynthWorks Design Inc. All rights reserved. +-- +-- Verbatim copies of this source file may be used and +-- distributed without restriction. +-- +-- This source file is free software; you can redistribute it +-- and/or modify it under the terms of the ARTISTIC License +-- as published by The Perl Foundation; either version 2.0 of +-- the License, or (at your option) any later version. +-- +-- This source is distributed in the hope that it will be +-- useful, but WITHOUT ANY WARRANTY; without even the implied +-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +-- PURPOSE. See the Artistic License for details. +-- +-- You should have received a copy of the license with this source. +-- If not download it from, +-- http://www.perlfoundation.org/artistic_license_2_0 +-- + +library ieee ; +use std.textio.all ; + +use work.NamePkg.all ; + +package OsvvmGlobalPkg is + -- FILE IO Global File Identifier -- Open using AlertLogPkg.TranscriptOpen +-- file TranscriptFile : text ; + + -- Shared Options Type used in OSVVM + type OsvvmOptionsType is (OPT_INIT_PARM_DETECT, OPT_USE_DEFAULT, DISABLED, FALSE, ENABLED, TRUE) ; + function IsEnabled (A : OsvvmOptionsType) return boolean ; -- Requires that TRUE is last and ENABLED is 2nd to last + function to_OsvvmOptionsType (A : boolean) return OsvvmOptionsType ; + + -- Defaults for String values + constant OSVVM_DEFAULT_ALERT_PREFIX : string := "%% Alert" ; + constant OSVVM_DEFAULT_LOG_PREFIX : string := "%% Log " ; + constant OSVVM_DEFAULT_WRITE_PREFIX : string := "%% " ; + constant OSVVM_DEFAULT_DONE_NAME : string := "DONE" ; + constant OSVVM_DEFAULT_PASS_NAME : string := "PASSED" ; + constant OSVVM_DEFAULT_FAIL_NAME : string := "FAILED" ; + constant OSVVM_STRING_INIT_PARM_DETECT : string := NUL & NUL & NUL ; + constant OSVVM_STRING_USE_DEFAULT : string := NUL & "" ; + + -- Coverage Settings + constant OSVVM_DEFAULT_WRITE_PASS_FAIL : OsvvmOptionsType := FALSE ; + constant OSVVM_DEFAULT_WRITE_BIN_INFO : OsvvmOptionsType := TRUE ; + constant OSVVM_DEFAULT_WRITE_COUNT : OsvvmOptionsType := TRUE ; + constant OSVVM_DEFAULT_WRITE_ANY_ILLEGAL : OsvvmOptionsType := FALSE ; + + ------------------------------------------------------------ + procedure SetOsvvmGlobalOptions ( + ------------------------------------------------------------ + WritePassFail : OsvvmOptionsType := OPT_INIT_PARM_DETECT ; + WriteBinInfo : OsvvmOptionsType := OPT_INIT_PARM_DETECT ; + WriteCount : OsvvmOptionsType := OPT_INIT_PARM_DETECT ; + WriteAnyIllegal : OsvvmOptionsType := OPT_INIT_PARM_DETECT ; + WritePrefix : string := OSVVM_STRING_INIT_PARM_DETECT ; + DoneName : string := OSVVM_STRING_INIT_PARM_DETECT ; + PassName : string := OSVVM_STRING_INIT_PARM_DETECT ; + FailName : string := OSVVM_STRING_INIT_PARM_DETECT + ) ; + + ------------------------------------------------------------ + -- Accessor Functions + function ResolveOsvvmOption(A, B, C : OsvvmOptionsType) return OsvvmOptionsType ; + function ResolveOsvvmOption(A, B, C, D : OsvvmOptionsType) return OsvvmOptionsType ; + function IsOsvvmStringSet (A : string) return boolean ; + function ResolveOsvvmOption(A, B : string) return string ; + function ResolveOsvvmOption(A, B, C : string) return string ; + function ResolveOsvvmOption(A, B, C, D : string) return string ; + + impure function ResolveOsvvmWritePrefix(A : String) return string ; + impure function ResolveOsvvmWritePrefix(A, B : String) return string ; + impure function ResolveOsvvmDoneName(A : String) return string ; + impure function ResolveOsvvmDoneName(A, B : String) return string ; + impure function ResolveOsvvmPassName(A : String) return string ; + impure function ResolveOsvvmPassName(A, B : String) return string ; + impure function ResolveOsvvmFailName(A : String) return string ; + impure function ResolveOsvvmFailName(A, B : String) return string ; + + impure function ResolveCovWritePassFail(A, B : OsvvmOptionsType) return OsvvmOptionsType ; -- Cov + impure function ResolveCovWriteBinInfo(A, B : OsvvmOptionsType) return OsvvmOptionsType ; -- Cov + impure function ResolveCovWriteCount(A, B : OsvvmOptionsType) return OsvvmOptionsType ; -- Cov + impure function ResolveCovWriteAnyIllegal(A, B : OsvvmOptionsType) return OsvvmOptionsType ; -- Cov + + procedure OsvvmDeallocate ; + + type OptionsPType is protected + procedure Set (A: OsvvmOptionsType) ; + impure function get return OsvvmOptionsType ; + end protected OptionsPType ; +end OsvvmGlobalPkg ; + +--- /////////////////////////////////////////////////////////////////////////// +--- /////////////////////////////////////////////////////////////////////////// +--- /////////////////////////////////////////////////////////////////////////// + +package body OsvvmGlobalPkg is + type OptionsPType is protected body + variable GlobalVar : OsvvmOptionsType ; + procedure Set (A : OsvvmOptionsType) is + begin + GlobalVar := A ; + end procedure Set ; + impure function get return OsvvmOptionsType is + begin + return GlobalVar ; + end function get ; + end protected body OptionsPType ; + + shared variable WritePrefixVar : NamePType ; + shared variable DoneNameVar : NamePType ; + shared variable PassNameVar : NamePType ; + shared variable FailNameVar : NamePType ; + shared variable WritePassFailVar : OptionsPType ; -- := FALSE ; + shared variable WriteBinInfoVar : OptionsPType ; -- := TRUE ; + shared variable WriteCountVar : OptionsPType ; -- := TRUE ; + shared variable WriteAnyIllegalVar : OptionsPType ; -- := FALSE ; + + function IsEnabled (A : OsvvmOptionsType) return boolean is + begin + return A >= ENABLED ; + end function IsEnabled ; + + function to_OsvvmOptionsType (A : boolean) return OsvvmOptionsType is + begin + if A then + return TRUE ; + else + return FALSE ; + end if ; + end function to_OsvvmOptionsType ; + + + ------------------------------------------------------------ + procedure SetOsvvmGlobalOptions ( + ------------------------------------------------------------ + WritePassFail : OsvvmOptionsType := OPT_INIT_PARM_DETECT ; + WriteBinInfo : OsvvmOptionsType := OPT_INIT_PARM_DETECT ; + WriteCount : OsvvmOptionsType := OPT_INIT_PARM_DETECT ; + WriteAnyIllegal : OsvvmOptionsType := OPT_INIT_PARM_DETECT ; + WritePrefix : string := OSVVM_STRING_INIT_PARM_DETECT ; + DoneName : string := OSVVM_STRING_INIT_PARM_DETECT ; + PassName : string := OSVVM_STRING_INIT_PARM_DETECT ; + FailName : string := OSVVM_STRING_INIT_PARM_DETECT + ) is + begin + if WritePassFail /= OPT_INIT_PARM_DETECT then + WritePassFailVar.Set(WritePassFail) ; + end if ; + if WriteBinInfo /= OPT_INIT_PARM_DETECT then + WriteBinInfoVar.Set(WriteBinInfo) ; + end if ; + if WriteCount /= OPT_INIT_PARM_DETECT then + WriteCountVar.Set(WriteCount) ; + end if ; + if WriteAnyIllegal /= OPT_INIT_PARM_DETECT then + WriteAnyIllegalVar.Set(WriteAnyIllegal) ; + end if ; + if WritePrefix /= OSVVM_STRING_INIT_PARM_DETECT then + WritePrefixVar.Set(WritePrefix) ; + end if ; + if DoneName /= OSVVM_STRING_INIT_PARM_DETECT then + DoneNameVar.Set(DoneName) ; + end if ; + if PassName /= OSVVM_STRING_INIT_PARM_DETECT then + PassNameVar.Set(PassName) ; + end if ; + if FailName /= OSVVM_STRING_INIT_PARM_DETECT then + FailNameVar.Set(FailName) ; + end if ; + end procedure SetOsvvmGlobalOptions ; + + ------------------------------------------------------------ + -- Accessor Functions + -- Local Function + function IsOsvvmOptionSet (A : OsvvmOptionsType) return boolean is + begin + return A > OPT_USE_DEFAULT ; + end function IsOsvvmOptionSet ; + + function ResolveOsvvmOption(A, B, C : OsvvmOptionsType) return OsvvmOptionsType is + begin + if IsOsvvmOptionSet(A) then + return A ; + elsif IsOsvvmOptionSet(B) then + return B ; + else + return C ; + end if ; + end function ResolveOsvvmOption ; + + function ResolveOsvvmOption(A, B, C, D : OsvvmOptionsType) return OsvvmOptionsType is + begin + if IsOsvvmOptionSet(A) then + return A ; + elsif IsOsvvmOptionSet(B) then + return B ; + elsif IsOsvvmOptionSet(C) then + return C ; + else + return D ; + end if ; + end function ResolveOsvvmOption ; + + -- Local Function + function IsOsvvmStringSet (A : string) return boolean is + begin + if A'length = 0 then -- Null strings permitted + return TRUE ; + else + return A(A'left) /= NUL ; + end if; + end function IsOsvvmStringSet ; + + function ResolveOsvvmOption(A, B : string) return string is + begin + if IsOsvvmStringSet(A) then + return A ; + else + return B ; + end if ; + end function ResolveOsvvmOption ; + + function ResolveOsvvmOption(A, B, C : string) return string is + begin + if IsOsvvmStringSet(A) then + return A ; + elsif IsOsvvmStringSet(B) then + return B ; + else + return C ; + end if ; + end function ResolveOsvvmOption ; + + function ResolveOsvvmOption(A, B, C, D : string) return string is + begin + if IsOsvvmStringSet(A) then + return A ; + elsif IsOsvvmStringSet(B) then + return B ; + elsif IsOsvvmStringSet(C) then + return C ; + else + return D ; + end if ; + end function ResolveOsvvmOption ; + + + impure function ResolveOsvvmWritePrefix(A : String) return string is + begin + return ResolveOsvvmOption(A, WritePrefixVar.GetOpt, OSVVM_DEFAULT_WRITE_PREFIX) ; + end function ResolveOsvvmWritePrefix ; + + impure function ResolveOsvvmWritePrefix(A, B : String) return string is + begin + return ResolveOsvvmOption(A, B, WritePrefixVar.GetOpt, OSVVM_DEFAULT_WRITE_PREFIX) ; + end function ResolveOsvvmWritePrefix ; + + impure function ResolveOsvvmDoneName(A : String) return string is + begin + return ResolveOsvvmOption(A, DoneNameVar.GetOpt, OSVVM_DEFAULT_DONE_NAME) ; + end function ResolveOsvvmDoneName ; + + impure function ResolveOsvvmDoneName(A, B : String) return string is + begin + return ResolveOsvvmOption(A, DoneNameVar.GetOpt, OSVVM_DEFAULT_DONE_NAME) ; + end function ResolveOsvvmDoneName ; + + impure function ResolveOsvvmPassName(A : String) return string is + begin + return ResolveOsvvmOption(A, PassNameVar.GetOpt, OSVVM_DEFAULT_PASS_NAME) ; + end function ResolveOsvvmPassName ; + + impure function ResolveOsvvmPassName(A, B : String) return string is + begin + return ResolveOsvvmOption(A, B, PassNameVar.GetOpt, OSVVM_DEFAULT_PASS_NAME) ; + end function ResolveOsvvmPassName ; + + impure function ResolveOsvvmFailName(A : String) return string is + begin + return ResolveOsvvmOption(A, FailNameVar.GetOpt, OSVVM_DEFAULT_FAIL_NAME) ; + end function ResolveOsvvmFailName ; + + impure function ResolveOsvvmFailName(A, B : String) return string is + begin + return ResolveOsvvmOption(A, B, FailNameVar.GetOpt, OSVVM_DEFAULT_FAIL_NAME) ; + end function ResolveOsvvmFailName ; + + impure function ResolveCovWritePassFail(A, B : OsvvmOptionsType) return OsvvmOptionsType is + begin + return ResolveOsvvmOption(A, B, WritePassFailVar.Get, OSVVM_DEFAULT_WRITE_PASS_FAIL) ; + end function ResolveCovWritePassFail ; -- Cov + + impure function ResolveCovWriteBinInfo(A, B : OsvvmOptionsType) return OsvvmOptionsType is + begin + return ResolveOsvvmOption(A, B, WriteBinInfoVar.Get, OSVVM_DEFAULT_WRITE_BIN_INFO) ; + end function ResolveCovWriteBinInfo ; -- Cov + + impure function ResolveCovWriteCount(A, B : OsvvmOptionsType) return OsvvmOptionsType is + begin + return ResolveOsvvmOption(A, B, WriteCountVar.Get, OSVVM_DEFAULT_WRITE_COUNT) ; + end function ResolveCovWriteCount ; -- Cov + + impure function ResolveCovWriteAnyIllegal(A, B : OsvvmOptionsType) return OsvvmOptionsType is + begin + return ResolveOsvvmOption(A, B, WriteAnyIllegalVar.Get, OSVVM_DEFAULT_WRITE_ANY_ILLEGAL) ; + end function ResolveCovWriteAnyIllegal ; -- Cov + + procedure OsvvmDeallocate is + begin + -- Free up space used by NamePType within OsvvmGlobalPkg + WritePrefixVar.Deallocate ; + DoneNameVar.Deallocate ; + PassNameVar.Deallocate ; + FailNameVar.Deallocate ; + WritePassFailVar.Set(FALSE) ; -- := FALSE ; + WriteBinInfoVar.Set(TRUE ) ; -- := TRUE ; + WriteCountVar.Set(TRUE ) ; -- := TRUE ; + WriteAnyIllegalVar.Set(FALSE) ; -- := FALSE ; + + end procedure OsvvmDeallocate ; + +end package body OsvvmGlobalPkg ; \ No newline at end of file diff --git a/test/OSVVM/RandomBasePkg.vhd b/OSVVM/RandomBasePkg.vhd old mode 100755 new mode 100644 similarity index 84% rename from test/OSVVM/RandomBasePkg.vhd rename to OSVVM/RandomBasePkg.vhd index ed13126..9dc00d8 --- a/test/OSVVM/RandomBasePkg.vhd +++ b/OSVVM/RandomBasePkg.vhd @@ -1,7 +1,7 @@ -- -- File Name: RandomBasePkg.vhd -- Design Unit Name: RandomBasePkg --- Revision: STANDARD VERSION, revision 2013.05 +-- Revision: STANDARD VERSION -- -- Maintainer: Jim Lewis email: jim@synthworks.com -- Contributor(s): @@ -38,9 +38,11 @@ -- Fixed abstraction by moving RandomParmType to RandomPkg.vhd -- 4/2013 2013.04 No Changes -- 5/2013 2013.05 No Changes +-- 1/2015 2015.01 Changed Assert/Report to Alert +-- 6/2015 2015.06 Changed GenRandSeed to impure -- -- --- Copyright (c) 2008 - 2013 by SynthWorks Design Inc. All rights reserved. +-- Copyright (c) 2008 - 2015 by SynthWorks Design Inc. All rights reserved. -- -- Verbatim copies of this source file may be used and -- distributed without restriction. @@ -64,6 +66,9 @@ library ieee ; use ieee.math_real.all ; use std.textio.all ; +use work.OsvvmGlobalPkg.all ; +use work.AlertLogPkg.all ; + -- comment out following 2 lines with VHDL-2008. Leave in for VHDL-2002 -- library ieee_proposed ; -- remove with VHDL-2008 -- use ieee_proposed.standard_additions.all ; -- remove with VHDL-2008 @@ -80,9 +85,9 @@ package RandomBasePkg is -- Translate from integer_vector, integer, or string to RandomSeedType -- Required by RandomPkg.InitSeed -- GenRandSeed makes sure all values are in a valid range - function GenRandSeed(IV : integer_vector) return RandomSeedType ; - function GenRandSeed(I : integer) return RandomSeedType ; - function GenRandSeed(S : string) return RandomSeedType ; + impure function GenRandSeed(IV : integer_vector) return RandomSeedType ; + impure function GenRandSeed(I : integer) return RandomSeedType ; + impure function GenRandSeed(S : string) return RandomSeedType ; -- IO for RandomSeedType. If use subtype, then create aliases here -- in a similar fashion VHDL-2008 std_logic_textio. @@ -93,8 +98,11 @@ package RandomBasePkg is procedure read (variable L: inout line ; A : out RandomSeedType ) ; end RandomBasePkg ; - ----------------------------------------------------------------- - ----------------------------------------------------------------- + +--- /////////////////////////////////////////////////////////////////////////// +--- /////////////////////////////////////////////////////////////////////////// +--- /////////////////////////////////////////////////////////////////////////// + package body RandomBasePkg is ----------------------------------------------------------------- @@ -126,7 +134,7 @@ package body RandomBasePkg is -- if 2 seed values are passed to GenRandSeed and they are -- in the above range, then they must remain unmodified. -- - function GenRandSeed(IV : integer_vector) return RandomSeedType is + impure function GenRandSeed(IV : integer_vector) return RandomSeedType is alias iIV : integer_vector(1 to IV'length) is IV ; variable Seed1 : integer ; variable Seed2 : integer ; @@ -134,7 +142,7 @@ package body RandomBasePkg is constant SEED2_MAX : integer := 2147483398 ; begin if iIV'Length <= 0 then -- no seed - report "%%FATAL: GenRandSeed received NULL integer_vector" severity failure ; + Alert(OSVVM_ALERTLOG_ID, "RandomBasePkg.GenRandSeed received NULL integer_vector", FAILURE) ; return (3, 17) ; -- if continue seed = (3, 17) elsif iIV'Length = 1 then -- one seed value @@ -156,7 +164,7 @@ package body RandomBasePkg is -- GenRandSeed -- transform a single integer into the internal seed -- - function GenRandSeed(I : integer) return RandomSeedType is + impure function GenRandSeed(I : integer) return RandomSeedType is variable result : integer_vector(1 to 2) ; begin result(1) := I ; @@ -170,7 +178,7 @@ package body RandomBasePkg is -- transform a string value into the internal seed -- usage: RV.GenRandSeed(RV'instance_path)); -- - function GenRandSeed(S : string) return RandomSeedType is + impure function GenRandSeed(S : string) return RandomSeedType is constant LEN : integer := S'length ; constant HALF_LEN : integer := LEN/2 ; alias revS : string(LEN downto 1) is S ; @@ -205,22 +213,22 @@ package body RandomBasePkg is ----------------------------------------------------------------- procedure read(variable L: inout line ; A : out RandomSeedType ; good : out boolean ) is - variable iGood : boolean ; + variable iReadValid : boolean ; begin for i in A'range loop - read(L, A(i), iGood) ; - exit when not iGood ; + read(L, A(i), iReadValid) ; + exit when not iReadValid ; end loop ; - good := iGood ; + good := iReadValid ; end procedure read ; ----------------------------------------------------------------- procedure read(variable L: inout line ; A : out RandomSeedType ) is - variable good : boolean ; + variable ReadValid : boolean ; begin - read(L, A, good) ; - assert good report "read[line, RandomSeedType] failed" severity error ; + read(L, A, ReadValid) ; + AlertIfNot(ReadValid, OSVVM_ALERTLOG_ID, "RandomBasePkg.read[line, RandomSeedType] failed", FAILURE) ; end procedure read ; end RandomBasePkg ; \ No newline at end of file diff --git a/test/OSVVM/RandomPkg.vhd b/OSVVM/RandomPkg.vhd old mode 100755 new mode 100644 similarity index 91% rename from test/OSVVM/RandomPkg.vhd rename to OSVVM/RandomPkg.vhd index 7546cc0..8c50658 --- a/test/OSVVM/RandomPkg.vhd +++ b/OSVVM/RandomPkg.vhd @@ -1,1646 +1,1647 @@ --- --- File Name : RandomPkg.vhd --- Design Unit Name : RandomPkg --- Revision : STANDARD VERSION, revision 2014.01 --- --- Maintainer : Jim Lewis email : jim@synthworks.com --- Contributor(s) : --- Jim Lewis email : jim@synthworks.com --- * --- --- * In writing procedures normal, poisson, the following sources were referenced : --- Wikipedia --- package rnd2 written by John Breen and Ken Christensen --- package RNG written by Gnanasekaran Swaminathan --- --- --- Description : --- RandomPType, a protected type, defined to hold randomization RandomSeeds and --- function methods to facilitate randomization with uniform and weighted --- distributions --- --- Developed for : --- SynthWorks Design Inc. --- VHDL Training Classes --- 11898 SW 128th Ave. Tigard, Or 97223 --- http ://www.SynthWorks.com --- --- Revision History : --- Date Version Description --- 12/2006 : 0.1 Initial revision --- Numerous revisions for VHDL Testbenches and Verification --- 02/2009 : 1.0 First Public Released Version --- 02/25/2009 1.1 Replaced reference to std_2008 with a reference to --- ieee_proposed.standard_additions.all ; --- 06/2010 1.2 Added Normal and Poisson distributions --- 03/2011 2.0 Major clean-up. --- Moved RandomParmType and control to here --- 07/2011 2.1 Bug fix to convenience functions for slv, unsigned, and signed. --- 06/2012 2.2 Removed '_' in the name of subprograms FavorBig and FavorSmall --- to make more consistent with other subprogram names --- 04/2013 2013.04 Changed DistInt --- Now returns input array range. --- For literals, no impact. It still returns 0 to N-1 (the default array range) --- Impacts named constants, signals, or variables. --- Added error checking to weight values --- Better Min, Max error handling in Uniform, FavorBig, FavorSmall, Normal, Poisson --- 5/2013 - Removed extra variable declaration in functions RandInt and RandReal --- 5/2013 2013.05 Big vector randomization added overloading RandUnsigned, RandSlv, and RandSigned --- Added NULL_RANGE_TYPE to minimize null range warnings --- 1/2014 2014.01 Added RandTime, RandReal(set), RandIntV, RandRealV, RandTimeV --- Made sort, revsort from SortListPkg_int visible via aliases --- --- Copyright (c) 2006 - 2014 by SynthWorks Design Inc. All rights reserved. --- --- Verbatim copies of this source file may be used and --- distributed without restriction. --- --- This source file is free software ; you can redistribute it --- and/or modify it under the terms of the ARTISTIC License --- as published by The Perl Foundation ; either version 2.0 of --- the License, or (at your option) any later version. --- --- This source is distributed in the hope that it will be --- useful, but WITHOUT ANY WARRANTY ; without even the implied --- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR --- PURPOSE. See the Artistic License for details. --- --- You should have received a copy of the license with this source. --- If not download it from, --- http ://www.perlfoundation.org/artistic_license_2_0 --- - -use work.RandomBasePkg.all ; -use work.SortListPkg_int.all ; - -use std.textio.all ; - -library ieee ; -use ieee.std_logic_1164.all ; -use ieee.numeric_std.all ; -use ieee.numeric_std_unsigned.all ; -use ieee.math_real.all ; - --- comment out following 3 lines with VHDL-2008. Leave in for VHDL-2002 --- library ieee_proposed ; -- remove with VHDL-2008 --- use ieee_proposed.standard_additions.all ; -- remove with VHDL-2008 --- use ieee_proposed.standard_textio_additions.all ; -- remove with VHDL-2008 - - -package RandomPkg is --- Uncomment the following with VHDL-2008 package generics. --- For now they are defined in the package RandomBasePkg.vhd --- package RandomGenericPkg is - -- generic ( - -- type RandomSeedType ; -- base type for randomization - -- procedure Uniform (Result : out real ; Seed : inout RandomSeedType) ; - -- function GenRandSeed(IV : integer_vector) return RandomSeedType ; - -- function GenRandSeed(I : integer) return RandomSeedType ; - -- function GenRandSeed(S : string) return RandomSeedType ; - -- ) ; - - -- make things from SortListPkg_int visible - alias sort is work.SortListPkg_int.sort[integer_vector return integer_vector] ; - alias revsort is work.SortListPkg_int.revsort[integer_vector return integer_vector] ; - - -- note NULL_RANGE_TYPE should probably be in std.standard - subtype NULL_RANGE_TYPE is integer range 0 downto 1 ; - constant NULL_INTV : integer_vector (NULL_RANGE_TYPE) := (others => 0) ; - - -- Supports DistValInt functionality - type DistRecType is record - Value : integer ; - Weight : integer ; - end record ; - type DistType is array (natural range <>) of DistRecType ; - - - -- Parameters for randomization - -- RandomDistType specifies the distribution to use for randomize - type RandomDistType is (NONE, UNIFORM, FAVOR_SMALL, FAVOR_BIG, NORMAL, POISSON) ; - - type RandomParmType is record - Distribution : RandomDistType ; - Mean : Real ; -- also used as probability of success - StdDeviation : Real ; -- also used as number of trials for binomial - end record ; - - -- RandomParm IO - function to_string(A : RandomDistType) return string ; - procedure write(variable L : inout line ; A : RandomDistType ) ; - procedure read(variable L : inout line ; A : out RandomDistType ; good : out boolean ) ; - procedure read(variable L : inout line ; A : out RandomDistType ) ; - function to_string(A : RandomParmType) return string ; - procedure write(variable L : inout line ; A : RandomParmType ) ; - procedure read(variable L : inout line ; A : out RandomParmType ; good : out boolean ) ; - procedure read(variable L : inout line ; A : out RandomParmType ) ; - - - type RandomPType is protected - -- Seed Manipulation - -- Known ambiguity between InitSeed with string and integer_vector - -- Recommendation, use : RV.InitSeed(RV'instance_path) ; - -- For integer_vector use either : RV.InitSeed(IV => (1,5)) ; - -- or : RV.InitSeed(integer_vector'(1,5)) ; - procedure InitSeed (S : string ) ; - procedure InitSeed (I : integer ) ; - procedure InitSeed (IV : integer_vector ) ; - - -- SetSeed & GetSeed : Used to save and restore seed values - procedure SetSeed (RandomSeedIn : RandomSeedType ) ; - impure function GetSeed return RandomSeedType ; - -- SeedRandom = SetSeed & GetSeed for SV compatibility - -- replace with aliases when they work in popular simulators - procedure SeedRandom (RandomSeedIn : RandomSeedType ) ; - impure function SeedRandom return RandomSeedType ; - -- alias SeedRandom is SetSeed [RandomSeedType] ; - -- alias SeedRandom is GetSeed [return RandomSeedType] ; - - -- Setting Randomization Parameters - -- Allows RandInt to have distributions other than uniform - procedure SetRandomParm (RandomParmIn : RandomParmType) ; - procedure SetRandomParm ( - Distribution : RandomDistType ; - Mean : Real := 0.0 ; - Deviation : Real := 0.0 - ) ; - impure function GetRandomParm return RandomParmType ; - impure function GetRandomParm return RandomDistType ; - - -- For compatibility with previous version - replace with alias - procedure SetRandomMode (RandomDistIn : RandomDistType) ; - -- alias SetRandomMode is SetRandomParm [RandomDistType, Real, Real] ; - - -- Base Randomization Distributions - -- Uniform : Generate a random number with a Uniform distribution - impure function Uniform (Min, Max : in real) return real ; - impure function Uniform (Min, Max : integer) return integer ; - impure function Uniform (Min, Max : integer ; Exclude : integer_vector) return integer ; - - -- FavorSmall - -- Generate random numbers with a greater number of small - -- values than large values - impure function FavorSmall (Min, Max : real) return real ; - impure function FavorSmall (Min, Max : integer) return integer ; - impure function FavorSmall (Min, Max : integer ; Exclude : integer_vector) return integer ; - - -- FavorBig - -- Generate random numbers with a greater number of large - -- values than small values - impure function FavorBig (Min, Max : real) return real ; - impure function FavorBig (Min, Max : integer) return integer ; - impure function FavorBig (Min, Max : integer ; Exclude : integer_vector) return integer ; - - -- Normal : Generate a random number with a normal distribution - impure function Normal (Mean, StdDeviation : real) return real ; - -- Normal + RandomVal >= Min and RandomVal < Max - impure function Normal (Mean, StdDeviation, Min, Max : real) return real ; - impure function Normal ( - Mean : real ; - StdDeviation : real ; - Min : integer ; - Max : integer ; - Exclude : integer_vector := NULL_INTV - ) return integer ; - - -- Poisson : Generate a random number with a poisson distribution - -- Discrete distribution = only generates integral values - impure function Poisson (Mean : real) return real ; - -- Poisson + RandomVal >= Min and RandomVal < Max - impure function Poisson (Mean, Min, Max : real) return real ; - impure function Poisson ( - Mean : real ; - Min : integer ; - Max : integer ; - Exclude : integer_vector := NULL_INTV - ) return integer ; - - - -- randomization with a range - impure function RandInt (Min, Max : integer) return integer ; - impure function RandReal(Min, Max : Real) return real ; - impure function RandTime (Min, Max : time ; Unit : time := ns) return time ; - impure function RandSlv (Min, Max, Size : natural) return std_logic_vector ; - impure function RandUnsigned (Min, Max, Size : natural) return Unsigned ; - impure function RandSigned (Min, Max : integer ; Size : natural ) return Signed ; - impure function RandIntV (Min, Max : integer ; Size : natural) return integer_vector ; - impure function RandIntV (Min, Max : integer ; Unique : natural ; Size : natural) return integer_vector ; - impure function RandRealV (Min, Max : real ; Size : natural) return real_vector ; - impure function RandTimeV (Min, Max : time ; Size : natural ; Unit : time := ns) return time_vector ; - impure function RandTimeV (Min, Max : time ; Unique : natural ; Size : natural ; Unit : time := ns) return time_vector ; - - - -- randomization with a range and exclude vector - impure function RandInt (Min, Max : integer ; Exclude : integer_vector ) return integer ; - impure function RandTime (Min, Max : time ; Exclude : time_vector ; Unit : time := ns) return time ; - impure function RandSlv (Min, Max : natural ; Exclude : integer_vector ; Size : natural ) return std_logic_vector ; - impure function RandUnsigned (Min, Max : natural ; Exclude : integer_vector ; Size : natural ) return Unsigned ; - impure function RandSigned (Min, Max : integer ; Exclude : integer_vector ; Size : natural ) return Signed ; - impure function RandIntV (Min, Max : integer ; Exclude : integer_vector ; Size : natural) return integer_vector ; - impure function RandIntV (Min, Max : integer ; Exclude : integer_vector ; Unique : natural ; Size : natural) return integer_vector ; - impure function RandTimeV (Min, Max : time ; Exclude : time_vector ; Size : natural ; Unit : in time := ns) return time_vector ; - impure function RandTimeV (Min, Max : time ; Exclude : time_vector ; Unique : natural ; Size : natural ; Unit : in time := ns) return time_vector ; - - - -- Randomly select a value within a set of values - impure function RandInt ( A : integer_vector ) return integer ; - impure function RandReal ( A : real_vector ) return real ; - impure function RandTime (A : time_vector) return time ; - impure function RandSlv (A : integer_vector ; Size : natural) return std_logic_vector ; - impure function RandUnsigned (A : integer_vector ; Size : natural) return Unsigned ; - impure function RandSigned (A : integer_vector ; Size : natural ) return Signed ; - impure function RandIntV (A : integer_vector ; Size : natural) return integer_vector ; - impure function RandIntV (A : integer_vector ; Unique : natural ; Size : natural) return integer_vector ; - impure function RandRealV (A : real_vector ; Size : natural) return real_vector ; - impure function RandRealV (A : real_vector ; Unique : natural ; Size : natural) return real_vector ; - impure function RandTimeV (A : time_vector ; Size : natural) return time_vector ; - impure function RandTimeV (A : time_vector ; Unique : natural ; Size : natural) return time_vector ; - - - -- Randomly select a value within a set of values with exclude values (so can skip last or last n) - impure function RandInt ( A, Exclude : integer_vector ) return integer ; - impure function RandReal ( A, Exclude : real_vector ) return real ; - impure function RandTime (A, Exclude : time_vector) return time ; - impure function RandSlv (A, Exclude : integer_vector ; Size : natural) return std_logic_vector ; - impure function RandUnsigned (A, Exclude : integer_vector ; Size : natural) return Unsigned ; - impure function RandSigned (A, Exclude : integer_vector ; Size : natural ) return Signed ; - impure function RandIntV (A, Exclude : integer_vector ; Size : natural) return integer_vector ; - impure function RandIntV (A, Exclude : integer_vector ; Unique : natural ; Size : natural) return integer_vector ; - impure function RandRealV (A, Exclude : real_vector ; Size : natural) return real_vector ; - impure function RandRealV (A, Exclude : real_vector ; Unique : natural ; Size : natural) return real_vector ; - impure function RandTimeV (A, Exclude : time_vector ; Size : natural) return time_vector ; - impure function RandTimeV (A, Exclude : time_vector ; Unique : natural ; Size : natural) return time_vector ; - - - -- Randomly select between 0 and N-1 based on the specified weight. - -- where N = number values in weight array - impure function DistInt ( Weight : integer_vector ) return integer ; - impure function DistSlv ( Weight : integer_vector ; Size : natural ) return std_logic_vector ; - impure function DistUnsigned ( Weight : integer_vector ; Size : natural ) return unsigned ; - impure function DistSigned ( Weight : integer_vector ; Size : natural ) return signed ; - - - -- Distribution with just weights and with exclude values - impure function DistInt ( Weight : integer_vector ; Exclude : integer_vector ) return integer ; - impure function DistSlv ( Weight : integer_vector ; Exclude : integer_vector ; Size : natural ) return std_logic_vector ; - impure function DistUnsigned ( Weight : integer_vector ; Exclude : integer_vector ; Size : natural ) return unsigned ; - impure function DistSigned ( Weight : integer_vector ; Exclude : integer_vector ; Size : natural ) return signed ; - - - -- Distribution with weight and value - impure function DistValInt ( A : DistType ) return integer ; - impure function DistValSlv ( A : DistType ; Size : natural) return std_logic_vector ; - impure function DistValUnsigned ( A : DistType ; Size : natural) return unsigned ; - impure function DistValSigned ( A : DistType ; Size : natural) return signed ; - - - -- Distribution with weight and value and with exclude values - impure function DistValInt ( A : DistType ; Exclude : integer_vector ) return integer ; - impure function DistValSlv ( A : DistType ; Exclude : integer_vector ; Size : natural) return std_logic_vector ; - impure function DistValUnsigned ( A : DistType ; Exclude : integer_vector ; Size : natural) return unsigned ; - impure function DistValSigned ( A : DistType ; Exclude : integer_vector ; Size : natural) return signed ; - - - -- Large vector handling. - impure function RandUnsigned (Size : natural) return unsigned ; - impure function RandSlv (Size : natural) return std_logic_vector ; - impure function RandSigned (Size : natural) return signed ; - impure function RandUnsigned (Max : Unsigned) return unsigned ; - impure function RandSlv (Max : std_logic_vector) return std_logic_vector ; - impure function RandSigned (Max : signed) return signed ; - impure function RandUnsigned (Min, Max : unsigned) return unsigned ; - impure function RandSlv (Min, Max : std_logic_vector) return std_logic_vector ; - impure function RandSigned (Min, Max : signed) return signed ; - - - -- Convenience Functions - impure function RandReal return real ; -- 0.0 to 1.0 - impure function RandReal(Max : Real) return real ; -- 0.0 to Max - impure function RandInt (Max : integer) return integer ; - impure function RandSlv (Max, Size : natural) return std_logic_vector ; - impure function RandUnsigned (Max, Size : natural) return Unsigned ; - impure function RandSigned (Max : integer ; Size : natural ) return Signed ; - - end protected RandomPType ; - -end RandomPkg ; - --- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -package body RandomPkg is - - ----------------------------------------------------------------- - -- Local Randomization Support - ----------------------------------------------------------------- - constant NULL_SLV : std_logic_vector (NULL_RANGE_TYPE) := (others => '0') ; - constant NULL_UV : unsigned (NULL_RANGE_TYPE) := (others => '0') ; - constant NULL_SV : signed (NULL_RANGE_TYPE) := (others => '0') ; - - ----------------------------------------------------------------- - -- Scale -- Scale a value to be within a given range - -- - function Scale (A, Min, Max : real) return real is - variable ValRange : Real ; - begin - ValRange := Max - Min ; - return A * ValRange + Min ; - end function Scale ; - - function Scale (A : real ; Min, Max : integer) return integer is - variable ValRange : real ; - variable rMin, rMax : real ; - begin - rMin := real(Min) - 0.5 ; - rMax := real(Max) + 0.5 ; - ValRange := rMax - rMin ; - return integer(round(A * ValRange + rMin)) ; - end function Scale ; - - -- create more smaller values - function FavorSmall (A : real) return real is - begin - return 1.0 - sqrt(A) ; - end FavorSmall ; - - -- create more larger values - -- alias FavorBig is sqrt[real return real] ; - function FavorBig (A : real) return real is - begin - return sqrt(A) ; - end FavorBig ; - - -- local. - function to_time_vector (A : integer_vector ; Unit : time) return time_vector is - variable result : time_vector(A'range) ; - begin - for i in A'range loop - result(i) := A(i) * Unit ; - end loop ; - return result ; - end function to_time_vector ; - - -- local - function to_integer_vector (A : time_vector ; Unit : time) return integer_vector is - variable result : integer_vector(A'range) ; - begin - for i in A'range loop - result(i) := A(i) / Unit ; - end loop ; - return result ; - end function to_integer_vector ; - - -- Local. Remove the exclude list from the list - integer_vector - procedure RemoveExclude(A, Exclude : integer_vector ; variable NewA : out integer_vector ; variable NewALength : inout natural ) is - alias norm_NewA : integer_vector(1 to NewA'length) is NewA ; - begin - NewALength := 0 ; - for i in A'range loop - if not inside(A(i), Exclude) then - NewALength := NewALength + 1 ; - norm_NewA(NewALength) := A(i) ; - end if ; - end loop ; - end procedure RemoveExclude ; - - -- Local. Inside - real_vector - function inside(A : real ; Exclude : real_vector) return boolean is - begin - for i in Exclude'range loop - if A = Exclude(i) then - return TRUE ; - end if ; - end loop ; - return FALSE ; - end function inside ; - - -- Local. Remove the exclude list from the list - real_vector - procedure RemoveExclude(A, Exclude : real_vector ; variable NewA : out real_vector ; variable NewALength : inout natural ) is - alias norm_NewA : real_vector(1 to NewA'length) is NewA ; - begin - NewALength := 0 ; - for i in A'range loop - if not inside(A(i), Exclude) then - NewALength := NewALength + 1 ; - norm_NewA(NewALength) := A(i) ; - end if ; - end loop ; - end procedure RemoveExclude ; - - -- Local. Inside - time_vector - function inside(A : time ; Exclude : time_vector) return boolean is - begin - for i in Exclude'range loop - if A = Exclude(i) then - return TRUE ; - end if ; - end loop ; - return FALSE ; - end function inside ; - - -- Local. Remove the exclude list from the list - time_vector - procedure RemoveExclude(A, Exclude : time_vector ; variable NewA : out time_vector ; variable NewALength : inout natural ) is - alias norm_NewA : time_vector(1 to NewA'length) is NewA ; - begin - NewALength := 0 ; - for i in A'range loop - if not inside(A(i), Exclude) then - NewALength := NewALength + 1 ; - norm_NewA(NewALength) := A(i) ; - end if ; - end loop ; - end procedure RemoveExclude ; - - - ----------------------------------------------------------------- - -- RandomParmType IO - ----------------------------------------------------------------- - ----------------------------------------------------------------- - function to_string(A : RandomDistType) return string is - begin - return RandomDistType'image(A) ; - end function to_string ; - - - ----------------------------------------------------------------- - procedure write(variable L : inout line ; A : RandomDistType ) is - begin - write(L, to_string(A)) ; - end procedure write ; - - - ----------------------------------------------------------------- - procedure read(variable L : inout line ; A : out RandomDistType ; good : out boolean ) is - variable strval : string(1 to 40) ; - variable len : natural ; - begin - -- procedure SREAD (L : inout LINE ; VALUE : out STRING ; STRLEN : out NATURAL) ; - sread(L, strval, len) ; - A := RandomDistType'value(strval(1 to len)) ; - good := len > 0 ; - end procedure read ; - - - ----------------------------------------------------------------- - procedure read(variable L : inout line ; A : out RandomDistType ) is - variable good : boolean ; - begin - read(L, A, good) ; - assert good report "read[line, RandomDistType] failed" severity error ; - end procedure read ; - - - ----------------------------------------------------------------- - function to_string(A : RandomParmType) return string is - begin - return RandomDistType'image(A.Distribution) & " " & - to_string(A.Mean, 2) & " " & to_string(A.StdDeviation, 2) ; - end function to_string ; - - - ----------------------------------------------------------------- - procedure write(variable L : inout line ; A : RandomParmType ) is - begin - write(L, to_string(A)) ; - end procedure write ; - - - ----------------------------------------------------------------- - procedure read(variable L : inout line ; A : out RandomParmType ; good : out boolean ) is - variable strval : string(1 to 40) ; - variable len : natural ; - variable igood : boolean ; - begin - loop - -- procedure SREAD (L : inout LINE ; VALUE : out STRING ; STRLEN : out NATURAL) ; - sread(L, strval, len) ; - A.Distribution := RandomDistType'value(strval(1 to len)) ; - igood := len > 0 ; - exit when not igood ; - - read(L, A.Mean, igood) ; - exit when not igood ; - - read(L, A.StdDeviation, igood) ; - exit ; - end loop ; - good := igood ; - end procedure read ; - - - ----------------------------------------------------------------- - procedure read(variable L : inout line ; A : out RandomParmType ) is - variable good : boolean ; - begin - read(L, A, good) ; - assert good report "read[line, RandomParmType] failed" severity error ; - end procedure read ; - - - - ----------------------------------------------------------------- - ----------------------------------------------------------------- - type RandomPType is protected body - -- - -- RandomSeed manipulation - -- - variable RandomSeed : RandomSeedType := GenRandSeed(integer_vector'(1,7)) ; - - procedure InitSeed (S : string ) is - begin - RandomSeed := GenRandSeed(S) ; - end procedure InitSeed ; - - procedure InitSeed (I : integer ) is - begin - RandomSeed := GenRandSeed(I) ; - end procedure InitSeed ; - - procedure InitSeed (IV : integer_vector ) is - begin - RandomSeed := GenRandSeed(IV) ; - end procedure InitSeed ; - - procedure SetSeed (RandomSeedIn : RandomSeedType ) is - begin - RandomSeed := RandomSeedIn ; - end procedure SetSeed ; - - procedure SeedRandom (RandomSeedIn : RandomSeedType ) is - begin - RandomSeed := RandomSeedIn ; - end procedure SeedRandom ; - - impure function GetSeed return RandomSeedType is - begin - return RandomSeed ; - end function GetSeed ; - - impure function SeedRandom return RandomSeedType is - begin - return RandomSeed ; - end function SeedRandom ; - - - -- - -- randomization mode - -- - variable RandomParm : RandomParmType ; -- left most values ok for init - - procedure SetRandomParm (RandomParmIn : RandomParmType) is - begin - RandomParm := RandomParmIn ; - end procedure SetRandomParm ; - - procedure SetRandomParm ( - Distribution : RandomDistType ; - Mean : Real := 0.0 ; - Deviation : Real := 0.0 - ) is - begin - RandomParm := RandomParmType'(Distribution, Mean, Deviation) ; - end procedure SetRandomParm ; - - - impure function GetRandomParm return RandomParmType is - begin - return RandomParm ; - end function GetRandomParm ; - - - impure function GetRandomParm return RandomDistType is - begin - return RandomParm.Distribution ; - end function GetRandomParm ; - - - -- For compatibility with previous version - procedure SetRandomMode (RandomDistIn : RandomDistType) is - begin - SetRandomParm(RandomDistIn) ; - end procedure SetRandomMode ; - - - -- - -- Base Randomization Distributions - -- - -- - -- Uniform : Generate a random number with a Uniform distribution - -- - impure function Uniform (Min, Max : in real) return real is - variable rRandomVal : real ; - begin - assert (Max >= Min) report "%%RandomPkg Uniform : Max < Min" severity FAILURE ; - Uniform(rRandomVal, RandomSeed) ; - return scale(rRandomVal, Min, Max) ; - end function Uniform ; - - impure function Uniform (Min, Max : integer) return integer is - variable rRandomVal : real ; - begin - assert (Max >= Min) report "%%RandomPkg Uniform : Max < Min" severity FAILURE ; - Uniform(rRandomVal, RandomSeed) ; - return scale(rRandomVal, Min, Max) ; - end function Uniform ; - - impure function Uniform (Min, Max : integer ; Exclude : integer_vector) return integer is - variable iRandomVal : integer ; - variable ExcludeList : SortListPType ; - variable count : integer ; - begin - ExcludeList.add(Exclude, Min, Max) ; - count := ExcludeList.count ; - iRandomVal := Uniform(Min, Max - count) ; - -- adjust count, note iRandomVal changes while checking. - for i in 1 to count loop - exit when iRandomVal < ExcludeList.Get(i) ; - iRandomVal := iRandomVal + 1 ; - end loop ; - ExcludeList.erase ; - return iRandomVal ; - end function Uniform ; - - - -- - -- FavorSmall - -- Generate random numbers with a greater number of small - -- values than large values - -- - impure function FavorSmall (Min, Max : real) return real is - variable rRandomVal : real ; - begin - assert (Max >= Min) report "%%RandomPkg FavorSmall : Max < Min" severity FAILURE ; - Uniform(rRandomVal, RandomSeed) ; - return scale(FavorSmall(rRandomVal), Min, Max) ; -- real - end function FavorSmall ; - - impure function FavorSmall (Min, Max : integer) return integer is - variable rRandomVal : real ; - begin - assert (Max >= Min) report "%%RandomPkg FavorSmall : Max < Min" severity FAILURE ; - Uniform(rRandomVal, RandomSeed) ; - return scale(FavorSmall(rRandomVal), Min, Max) ; -- integer - end function FavorSmall ; - - impure function FavorSmall (Min, Max : integer ; Exclude : integer_vector) return integer is - variable iRandomVal : integer ; - variable ExcludeList : SortListPType ; - variable count : integer ; - begin - ExcludeList.add(Exclude, Min, Max) ; - count := ExcludeList.count ; - iRandomVal := FavorSmall(Min, Max - count) ; - -- adjust count, note iRandomVal changes while checking. - for i in 1 to count loop - exit when iRandomVal < ExcludeList.Get(i) ; - iRandomVal := iRandomVal + 1 ; - end loop ; - ExcludeList.erase ; - return iRandomVal ; - end function FavorSmall ; - - - -- - -- FavorBig - -- Generate random numbers with a greater number of large - -- values than small values - -- - impure function FavorBig (Min, Max : real) return real is - variable rRandomVal : real ; - begin - assert (Max >= Min) report "%%RandomPkg FavorBig : Max < Min" severity FAILURE ; - Uniform(rRandomVal, RandomSeed) ; - return scale(FavorBig(rRandomVal), Min, Max) ; -- real - end function FavorBig ; - - impure function FavorBig (Min, Max : integer) return integer is - variable rRandomVal : real ; - begin - assert (Max >= Min) report "%%RandomPkg FavorBig : Max < Min" severity FAILURE ; - Uniform(rRandomVal, RandomSeed) ; - return scale(FavorBig(rRandomVal), Min, Max) ; -- integer - end function FavorBig ; - - impure function FavorBig (Min, Max : integer ; Exclude : integer_vector) return integer is - variable iRandomVal : integer ; - variable ExcludeList : SortListPType ; - variable count : integer ; - begin - ExcludeList.add(Exclude, Min, Max) ; - count := ExcludeList.count ; - iRandomVal := FavorBig(Min, Max - count) ; - -- adjust count, note iRandomVal changes while checking. - for i in 1 to count loop - exit when iRandomVal < ExcludeList.Get(i) ; - iRandomVal := iRandomVal + 1 ; - end loop ; - ExcludeList.erase ; - return iRandomVal ; - end function FavorBig ; - - - ----------------------------------------------------------------- - -- Normal - -- Generate a random number with a normal distribution - -- - -- Use Box Muller, per Wikipedia : - -- http ://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform - -- - -- Use polar method, per Wikipedia : - -- http ://en.wikipedia.org/wiki/Marsaglia_polar_method - -- - impure function Normal (Mean, StdDeviation : real) return real is - variable x01, y01 : real ; - variable StdNormalDist : real ; -- mean 0, variance 1 - begin - -- add this check to set parameters? - if StdDeviation < 0.0 then - report "standard deviation must be >= 0.0" severity failure ; - return -1.0 ; - end if ; - - -- Box Muller - Uniform (x01, RandomSeed) ; - Uniform (y01, RandomSeed) ; - StdNormalDist := sqrt(-2.0 * log(x01)) * cos(math_2_pi*y01) ; - - -- Polar form rejected due to mean 50.0, std deviation = 5 resulted - -- in a median of 49 - -- -- find two Uniform distributed values with range -1 to 1 - -- -- that satisify S = X **2 + Y**2 < 1.0 - -- loop - -- Uniform (x01, RandomSeed) ; - -- Uniform (y01, RandomSeed) ; - -- x := 2.0 * x01 - 1.0 ; -- scale to -1 to 1 - -- y := 2.0 * y01 - 1.0 ; - -- s := x*x + y*y ; - -- exit when s < 1.0 and s > 0.0 ; - -- end loop ; - - -- -- Calculate Standard Normal Distribution - -- StdNormalDist := x * sqrt((-2.0 * log(s)) / s) ; - - -- Convert to have Mean and StdDeviation - return StdDeviation * StdNormalDist + Mean ; - end function Normal ; - - - -- Normal + RandomVal >= Min and RandomVal <= Max - impure function Normal (Mean, StdDeviation, Min, Max : real) return real is - variable rRandomVal : real ; - begin - if Max < Min then - report "%%RandomPkg Normal : Max < Min" severity FAILURE ; - else - loop - rRandomVal := Normal (Mean, StdDeviation) ; - exit when rRandomVal >= Min and rRandomVal <= Max ; - end loop ; - end if ; - return rRandomVal ; - end function Normal ; - - -- Normal + RandomVal >= Min and RandomVal <= Max - impure function Normal ( - Mean : real ; - StdDeviation : real ; - Min : integer ; - Max : integer ; - Exclude : integer_vector := NULL_INTV - ) return integer is - variable iRandomVal : integer ; - begin - if Max < Min then - report "%%RandomPkg Normal : Max < Min" severity FAILURE ; - else - loop - iRandomVal := integer(round( Normal(Mean, StdDeviation) )) ; - exit when iRandomVal >= Min and iRandomVal <= Max and - not inside(iRandomVal, Exclude) ; - end loop ; - end if ; - return iRandomVal ; - end function Normal ; - - - ----------------------------------------------------------------- - -- Poisson - -- Generate a random number with a poisson distribution - -- Discrete distribution = only generates integral values - -- - -- Use knuth method, per Wikipedia : - -- http ://en.wikipedia.org/wiki/Poisson_distribution - -- - impure function Poisson (Mean : real) return real is - variable Product : Real := 1.0 ; - variable Bound : Real := 0.0 ; - variable UniformRand : Real := 0.0 ; - variable PoissonRand : Real := 0.0 ; - begin - Bound := exp(-1.0 * Mean) ; - Product := 1.0 ; - - -- add this check to set parameters? - if Mean <= 0.0 or Bound <= 0.0 then - report "Poisson : Mean < 0 or too large. Mean = " & real'image(Mean) severity failure ; - return -1.0 ; - end if ; - - while (Product >= Bound) loop - PoissonRand := PoissonRand + 1.0 ; - Uniform(UniformRand, RandomSeed) ; - Product := Product * UniformRand ; - end loop ; - return PoissonRand ; - end function Poisson ; -- no range - - -- Poisson + RandomVal >= Min and RandomVal < Max - impure function Poisson (Mean, Min, Max : real) return real is - variable rRandomVal : real ; - begin - if Max < Min then - report "%%RandomPkg Poisson : Max < Min" severity FAILURE ; - else - loop - rRandomVal := Poisson (Mean) ; - exit when rRandomVal >= Min and rRandomVal <= Max ; - end loop ; - end if ; - return rRandomVal ; - end function Poisson ; - - impure function Poisson ( - Mean : real ; - Min : integer ; - Max : integer ; - Exclude : integer_vector := NULL_INTV - ) return integer is - variable iRandomVal : integer ; - begin - if Max < Min then - report "%%RandomPkg Poisson : Max < Min" severity FAILURE ; - else - loop - iRandomVal := integer(round( Poisson (Mean) )) ; - exit when iRandomVal >= Min and iRandomVal <= Max and - not inside(iRandomVal, Exclude) ; - end loop ; - end if ; - return iRandomVal ; - end function Poisson ; - - - -- - -- integer randomization with a range - -- Distribution determined by RandomParm - -- - impure function RandInt (Min, Max : integer) return integer is - begin - case RandomParm.Distribution is - when NONE | UNIFORM => return Uniform(Min, Max) ; - when FAVOR_SMALL => return FavorSmall(Min, Max) ; - when FAVOR_BIG => return FavorBig (Min, Max) ; - when NORMAL => return Normal(RandomParm.Mean, RandomParm.StdDeviation, Min, Max) ; - when POISSON => return Poisson(RandomParm.Mean, Min, Max) ; - when others => - report "RandomPkg : distribution not implemented" severity failure ; - return integer'low ; - end case ; - end function RandInt ; - - -- - -- real randomization with a range - -- Distribution determined by RandomParm - -- - impure function RandReal(Min, Max : Real) return real is - begin - case RandomParm.Distribution is - when NONE | UNIFORM => return Uniform(Min, Max) ; - when FAVOR_SMALL => return FavorSmall(Min, Max) ; - when FAVOR_BIG => return FavorBig (Min, Max) ; - when NORMAL => return Normal(RandomParm.Mean, RandomParm.StdDeviation, Min, Max) ; - when POISSON => return Poisson(RandomParm.Mean, Min, Max) ; - when others => - report "RandomPkg : distribution not implemented" severity failure ; - return real(integer'low) ; - end case ; - end function RandReal ; - - impure function RandTime (Min, Max : time ; Unit :time := ns) return time is - variable IntVal : integer ; - begin - -- if Max - Min > 2**31 result will be out of range - IntVal := RandInt(0, (Max - Min)/Unit) ; - Return Min + Unit*IntVal ; - end function RandTime ; - - impure function RandSlv (Min, Max, Size : natural) return std_logic_vector is - begin - return std_logic_vector(to_unsigned(RandInt(Min, Max), Size)) ; - end function RandSlv ; - - impure function RandUnsigned (Min, Max, Size : natural) return Unsigned is - begin - return to_unsigned(RandInt(Min, Max), Size) ; - end function RandUnsigned ; - - impure function RandSigned (Min, Max : integer ; Size : natural ) return Signed is - begin - return to_signed(RandInt(Min, Max), Size) ; - end function RandSigned ; - - impure function RandIntV (Min, Max : integer ; Size : natural) return integer_vector is - variable result : integer_vector(1 to Size) ; - begin - for i in result'range loop - result(i) := RandInt(Min, Max) ; - end loop ; - return result ; - end function RandIntV ; - - impure function RandIntV (Min, Max : integer ; Unique : natural ; Size : natural) return integer_vector is - variable result : integer_vector(1 to Size) ; - variable iUnique : natural ; - begin - -- if Unique = 0, it is more efficient to call RandIntV(Min, Max, Size) - iUnique := Unique ; - if Max-Min+1 < Unique then - report "RandIntV / RandRealV / RandTimeV: Unique > number of values available" severity failure ; - iUnique := Max-Min+1 ; - end if ; - for i in result'range loop - result(i) := RandInt(Min, Max, result(maximum(1, 1 + i - iUnique) to Size)) ; - end loop ; - return result ; - end function RandIntV ; - - impure function RandRealV (Min, Max : real ; Size : natural) return real_vector is - variable result : real_vector(1 to Size) ; - begin - for i in result'range loop - result(i) := RandReal(Min, Max) ; - end loop ; - return result ; - end function RandRealV ; - - impure function RandTimeV (Min, Max : time ; Size : natural ; Unit : time := ns) return time_vector is - variable result : time_vector(1 to Size) ; - begin - for i in result'range loop - result(i) := RandTime(Min, Max, Unit) ; - end loop ; - return result ; - end function RandTimeV ; - - impure function RandTimeV (Min, Max : time ; Unique : natural ; Size : natural ; Unit : time := ns) return time_vector is - begin - -- if Unique = 0, it is more efficient to call RandTimeV(Min, Max, Size) - return to_time_vector(RandIntV(Min/Unit, Max/Unit, Unique, Size), Unit) ; - end function RandTimeV ; - - - -- - -- integer randomization with a range and exclude vector - -- Distribution determined by RandomParm - -- - impure function RandInt (Min, Max : integer ; Exclude : integer_vector ) return integer is - begin - case RandomParm.Distribution is - when NONE | UNIFORM => return Uniform(Min, Max, Exclude) ; - when FAVOR_SMALL => return FavorSmall(Min, Max, Exclude) ; - when FAVOR_BIG => return FavorBig (Min, Max, Exclude) ; - when NORMAL => return Normal(RandomParm.Mean, RandomParm.StdDeviation, Min, Max, Exclude) ; - when POISSON => return Poisson(RandomParm.Mean, Min, Max, Exclude) ; - when others => - report "RandomPkg : distribution not implemented" severity failure ; - return integer'low ; - end case ; - end function RandInt ; - - impure function RandTime (Min, Max : time ; Exclude : time_vector ; Unit : time := ns) return time is - variable IntVal : integer ; - begin - -- if Min or Max > 2**31 value will be out of range - return RandInt(Min/Unit, Max/Unit, to_integer_vector(Exclude, Unit)) * Unit ; - end function RandTime ; - - impure function RandSlv (Min, Max : natural ; Exclude : integer_vector ; Size : natural ) return std_logic_vector is - begin - return std_logic_vector(to_unsigned(RandInt(Min, Max, Exclude), Size)) ; - end function RandSlv ; - - impure function RandUnsigned (Min, Max : natural ; Exclude : integer_vector ; Size : natural ) return Unsigned is - begin - return to_unsigned(RandInt(Min, Max, Exclude), Size) ; - end function RandUnsigned ; - - impure function RandSigned (Min, Max : integer ; Exclude : integer_vector ; Size : natural ) return Signed is - begin - return to_signed(RandInt(Min, Max, Exclude), Size) ; - end function RandSigned ; - - impure function RandIntV (Min, Max : integer ; Exclude : integer_vector ; Size : natural) return integer_vector is - variable result : integer_vector(1 to Size) ; - begin - for i in result'range loop - result(i) := RandInt(Min, Max, Exclude) ; - end loop ; - return result ; - end function RandIntV ; - - impure function RandIntV (Min, Max : integer ; Exclude : integer_vector ; Unique : natural ; Size : natural) return integer_vector is - variable ResultPlus : integer_vector(1 to Size + Exclude'length) ; - begin - -- if Unique = 0, it is more efficient to call RandIntV(Min, Max, Size) - ResultPlus(Size+1 to ResultPlus'right) := Exclude ; - for i in 1 to Size loop - ResultPlus(i) := RandInt(Min, Max, ResultPlus(maximum(1, 1 + i - Unique) to ResultPlus'right)) ; - end loop ; - return ResultPlus(1 to Size) ; - end function RandIntV ; - - impure function RandTimeV (Min, Max : time ; Exclude : time_vector ; Size : natural ; Unit : in time := ns) return time_vector is - begin - return to_time_vector( RandIntV(Min/Unit, Max/Unit, to_integer_vector(Exclude, Unit), Size), Unit ) ; - end function RandTimeV ; - - impure function RandTimeV (Min, Max : time ; Exclude : time_vector ; Unique : natural ; Size : natural ; Unit : in time := ns) return time_vector is - begin - -- if Unique = 0, it is more efficient to call RandIntV(Min, Max, Size) - return to_time_vector( RandIntV(Min/Unit, Max/Unit, to_integer_vector(Exclude, Unit), Unique, Size), Unit ) ; - end function RandTimeV ; - - - - -- - -- Randomly select a value within a set of values - -- Distribution determined by RandomParm - -- - impure function RandInt ( A : integer_vector ) return integer is - alias A_norm : integer_vector(1 to A'length) is A ; - begin - return A_norm( RandInt(1, A'length) ) ; - end function RandInt ; - - impure function RandReal ( A : real_vector ) return real is - alias A_norm : real_vector(1 to A'length) is A ; - begin - return A_norm( RandInt(1, A'length) ) ; - end function RandReal ; - - impure function RandTime ( A : time_vector ) return time is - alias A_norm : time_vector(1 to A'length) is A ; - begin - return A_norm( RandInt(1, A'length) ) ; - end function RandTime ; - - impure function RandSlv (A : integer_vector ; Size : natural) return std_logic_vector is - begin - return std_logic_vector(to_unsigned(RandInt(A), Size)) ; - end function RandSlv ; - - impure function RandUnsigned (A : integer_vector ; Size : natural) return Unsigned is - begin - return to_unsigned(RandInt(A), Size) ; - end function RandUnsigned ; - - impure function RandSigned (A : integer_vector ; Size : natural ) return Signed is - begin - return to_signed(RandInt(A), Size) ; - end function RandSigned ; - - impure function RandIntV (A : integer_vector ; Size : natural) return integer_vector is - variable result : integer_vector(1 to Size) ; - begin - for i in result'range loop - result(i) := RandInt(A) ; - end loop ; - return result ; - end function RandIntV ; - - impure function RandIntV (A : integer_vector ; Unique : natural ; Size : natural) return integer_vector is - variable result : integer_vector(1 to Size) ; - variable iUnique : natural ; - begin - -- if Unique = 0, it is more efficient to call RandIntV(A, Size) - -- require A'length >= Unique - iUnique := Unique ; - if A'length < Unique then - report "RandIntV: Unique > length of set of values" severity failure ; - iUnique := A'length ; - end if ; - for i in result'range loop - result(i) := RandInt(A, result(maximum(1, 1 + i - iUnique) to Size)) ; - end loop ; - return result ; - end function RandIntV ; - - impure function RandRealV (A : real_vector ; Size : natural) return real_vector is - variable result : real_vector(1 to Size) ; - begin - for i in result'range loop - result(i) := RandReal(A) ; - end loop ; - return result ; - end function RandRealV ; - - impure function RandRealV (A : real_vector ; Unique : natural ; Size : natural) return real_vector is - alias A_norm : real_vector(1 to A'length) is A ; - variable result : real_vector(1 to Size) ; - variable IntResult : integer_vector(result'range) ; - begin - -- randomly generate indices - IntResult := RandIntV(1, A'length, Unique, Size) ; - -- translate indicies into result values - for i in result'range loop - result(i) := A_norm(IntResult(i)) ; - end loop ; - return result ; - end function RandRealV ; - - impure function RandTimeV (A : time_vector ; Size : natural) return time_vector is - variable result : time_vector(1 to Size) ; - begin - for i in result'range loop - result(i) := RandTime(A) ; - end loop ; - return result ; - end function RandTimeV ; - - impure function RandTimeV (A : time_vector ; Unique : natural ; Size : natural) return time_vector is - alias A_norm : time_vector(1 to A'length) is A ; - variable result : time_vector(1 to Size) ; - variable IntResult : integer_vector(result'range) ; - begin - -- randomly generate indices - IntResult := RandIntV(1, A'length, Unique, Size) ; - -- translate indicies into result values - for i in result'range loop - result(i) := A_norm(IntResult(i)) ; - end loop ; - return result ; - end function RandTimeV ; - - - -- - -- Randomly select a value within a set of values with exclude values (so can skip last or last n) - -- Distribution determined by RandomParm - -- - - impure function RandInt ( A, Exclude : integer_vector ) return integer is - variable NewA : integer_vector(1 to A'length) ; - variable NewALength : natural ; - begin - -- Remove Exclude from A - RemoveExclude(A, Exclude, NewA, NewALength) ; - -- Randomize Index - return NewA(RandInt(1, NewALength)) ; - end function RandInt ; - - impure function RandReal ( A, Exclude : real_vector ) return real is - variable NewA : real_vector(1 to A'length) ; - variable NewALength : natural ; - begin - -- Remove Exclude from A - RemoveExclude(A, Exclude, NewA, NewALength) ; - -- Randomize Index - return NewA(RandInt(1, NewALength)) ; - end function RandReal ; - - impure function RandTime ( A, Exclude : time_vector ) return time is - variable NewA : time_vector(1 to A'length) ; - variable NewALength : natural ; - begin - -- Remove Exclude from A - RemoveExclude(A, Exclude, NewA, NewALength) ; - -- Randomize Index - return NewA(RandInt(1, NewALength)) ; - end function RandTime ; - - impure function RandSlv (A, Exclude : integer_vector ; Size : natural) return std_logic_vector is - begin - return std_logic_vector(to_unsigned(RandInt(A, Exclude), Size)) ; - end function RandSlv ; - - impure function RandUnsigned (A, Exclude : integer_vector ; Size : natural) return Unsigned is - begin - return to_unsigned(RandInt(A, Exclude), Size) ; - end function RandUnsigned ; - - impure function RandSigned (A, Exclude : integer_vector ; Size : natural ) return Signed is - begin - return to_signed(RandInt(A, Exclude), Size) ; - end function RandSigned ; - - impure function RandIntV (A, Exclude : integer_vector ; Size : natural) return integer_vector is - variable result : integer_vector(1 to Size) ; - variable NewA : integer_vector(1 to A'length) ; - variable NewALength : natural ; - begin - -- Remove Exclude from A - RemoveExclude(A, Exclude, NewA, NewALength) ; - -- Randomize Index - for i in result'range loop - result(i) := NewA(RandInt(1, NewALength)) ; - end loop ; - return result ; - end function RandIntV ; - - impure function RandIntV (A, Exclude : integer_vector ; Unique : natural ; Size : natural) return integer_vector is - variable result : integer_vector(1 to Size) ; - variable NewA : integer_vector(1 to A'length) ; - variable NewALength, iUnique : natural ; - begin - -- if Unique = 0, it is more efficient to call RandIntV(Min, Max, Size) - -- Remove Exclude from A - RemoveExclude(A, Exclude, NewA, NewALength) ; - -- Require NewALength >= Unique - iUnique := Unique ; - if NewALength < Unique then - report "RandIntV: Unique > Length of Set A - Exclude" severity failure ; - iUnique := NewALength ; - end if ; - -- Randomize using exclude list of Unique # of newly generated values - for i in result'range loop - result(i) := RandInt(NewA(1 to NewALength), result(maximum(1, 1 + i - iUnique) to Size)) ; - end loop ; - return result ; - end function RandIntV ; - - impure function RandRealV (A, Exclude : real_vector ; Size : natural) return real_vector is - variable result : real_vector(1 to Size) ; - variable NewA : real_vector(1 to A'length) ; - variable NewALength : natural ; - begin - -- Remove Exclude from A - RemoveExclude(A, Exclude, NewA, NewALength) ; - -- Randomize Index - for i in result'range loop - result(i) := NewA(RandInt(1, NewALength)) ; - end loop ; - return result ; - end function RandRealV ; - - impure function RandRealV (A, Exclude : real_vector ; Unique : natural ; Size : natural) return real_vector is - variable result : real_vector(1 to Size) ; - variable NewA : real_vector(1 to A'length) ; - variable NewALength, iUnique : natural ; - begin - -- if Unique = 0, it is more efficient to call RandRealV(Min, Max, Size) - -- Remove Exclude from A - RemoveExclude(A, Exclude, NewA, NewALength) ; - -- Require NewALength >= Unique - iUnique := Unique ; - if NewALength < Unique then - report "RandRealV: Unique > Length of Set A - Exclude" severity failure ; - iUnique := NewALength ; - end if ; - -- Randomize using exclude list of Unique # of newly generated values - for i in result'range loop - result(i) := RandReal(NewA(1 to NewALength), result(maximum(1, 1 + i - iUnique) to Size)) ; - end loop ; - return result ; - end function RandRealV ; - - impure function RandTimeV (A, Exclude : time_vector ; Size : natural) return time_vector is - variable result : time_vector(1 to Size) ; - variable NewA : time_vector(1 to A'length) ; - variable NewALength : natural ; - begin - -- Remove Exclude from A - RemoveExclude(A, Exclude, NewA, NewALength) ; - -- Randomize Index - for i in result'range loop - result(i) := NewA(RandInt(1, NewALength)) ; - end loop ; - return result ; - end function RandTimeV ; - - impure function RandTimeV (A, Exclude : time_vector ; Unique : natural ; Size : natural) return time_vector is - variable result : time_vector(1 to Size) ; - variable NewA : time_vector(1 to A'length) ; - variable NewALength, iUnique : natural ; - begin - -- if Unique = 0, it is more efficient to call RandRealV(Min, Max, Size) - -- Remove Exclude from A - RemoveExclude(A, Exclude, NewA, NewALength) ; - -- Require NewALength >= Unique - iUnique := Unique ; - if NewALength < Unique then - report "RandTimeV: Unique > Length of Set A - Exclude" severity failure ; - iUnique := NewALength ; - end if ; - -- Randomize using exclude list of Unique # of newly generated values - for i in result'range loop - result(i) := RandTime(NewA(1 to NewALength), result(maximum(1, 1 + i - iUnique) to Size)) ; - end loop ; - return result ; - end function RandTimeV ; - - - -- - -- Basic Discrete Distributions - -- Always uses Uniform - -- - impure function DistInt ( Weight : integer_vector ) return integer is - variable DistArray : integer_vector(weight'range) ; - variable sum : integer ; - variable iRandomVal : integer ; - begin - DistArray := Weight ; - sum := 0 ; - for i in DistArray'range loop - DistArray(i) := DistArray(i) + sum ; - if DistArray(i) < sum then - report "DistInt failed : negative weight or sum > 31 bits" - severity failure ; - return DistArray'low ; -- allows debugging vs integer'left, out of range - end if ; - sum := DistArray(i) ; - end loop ; - if sum >= 1 then - iRandomVal := Uniform(1, sum) ; - for i in DistArray'range loop - if iRandomVal <= DistArray(i) then - return i ; - end if ; - end loop ; - report "DistInt : randomization failed" severity failure ; - else - report "DistInt : No randomizatoin weights" severity failure ; - end if ; - return DistArray'low ; -- allows debugging vs integer'left, out of range - end function DistInt ; - - impure function DistSlv ( Weight : integer_vector ; Size : natural ) return std_logic_vector is - begin - return std_logic_vector(to_unsigned(DistInt(Weight), Size)) ; - end function DistSlv ; - - impure function DistUnsigned ( Weight : integer_vector ; Size : natural ) return unsigned is - begin - return to_unsigned(DistInt(Weight), Size) ; - end function DistUnsigned ; - - impure function DistSigned ( Weight : integer_vector ; Size : natural ) return signed is - begin - return to_signed(DistInt(Weight), Size) ; - end function DistSigned ; - - - -- - -- Basic Distributions with exclude values (so can skip last or last n) - -- Always uses Uniform via DistInt - -- - impure function DistInt ( Weight : integer_vector ; Exclude : integer_vector ) return integer is - variable DistArray : integer_vector(weight'range) ; - variable ExcludeTemp : integer ; - begin - DistArray := Weight ; - for i in Exclude'range loop - ExcludeTemp := Exclude(i) ; - if ExcludeTemp >= DistArray'low and ExcludeTemp <= DistArray'high then - DistArray(ExcludeTemp) := 0 ; - end if ; - end loop ; - return DistInt(DistArray) ; - end function DistInt ; - - impure function DistSlv ( Weight : integer_vector ; Exclude : integer_vector ; Size : natural ) return std_logic_vector is - begin - return std_logic_vector(to_unsigned(DistInt(Weight, Exclude), Size)) ; - end function DistSlv ; - - impure function DistUnsigned ( Weight : integer_vector ; Exclude : integer_vector ; Size : natural ) return unsigned is - begin - return to_unsigned(DistInt(Weight, Exclude), Size) ; - end function DistUnsigned ; - - impure function DistSigned ( Weight : integer_vector ; Exclude : integer_vector ; Size : natural ) return signed is - begin - return to_signed(DistInt(Weight, Exclude), Size) ; - end function DistSigned ; - - - -- - -- Distribution for sparse values - -- Always uses Uniform via DistInt - -- - impure function DistValInt ( A : DistType ) return integer is - variable DistArray : integer_vector(0 to A'length -1) ; - alias DistRecArray : DistType(DistArray'range) is A ; - begin - for i in DistArray'range loop - DistArray(i) := DistRecArray(i).Weight ; - end loop ; - return DistRecArray(DistInt(DistArray)).Value ; - end function DistValInt ; - - impure function DistValSlv ( A : DistType ; Size : natural ) return std_logic_vector is - begin - return std_logic_vector(to_unsigned(DistValInt(A), Size)) ; - end function DistValSlv ; - - impure function DistValUnsigned ( A : DistType ; Size : natural ) return unsigned is - begin - return to_unsigned(DistValInt(A), Size) ; - end function DistValUnsigned ; - - impure function DistValSigned ( A : DistType ; Size : natural ) return signed is - begin - return to_signed(DistValInt(A), Size) ; - end function DistValSigned ; - - - -- - -- Distribution for sparse values with exclude values (so can skip last or last n) - -- Always uses Uniform via DistInt - -- - impure function DistValInt ( A : DistType ; Exclude : integer_vector ) return integer is - variable DistArray : integer_vector(0 to A'length -1) ; - alias DistRecArray : DistType(DistArray'range) is A ; - begin - for i in DistRecArray'range loop - if inside(DistRecArray(i).Value, exclude) then - DistArray(i) := 0 ; -- exclude - else - DistArray(i) := DistRecArray(i).Weight ; - end if ; - end loop ; - return DistRecArray(DistInt(DistArray)).Value ; - end function DistValInt ; - - impure function DistValSlv ( A : DistType ; Exclude : integer_vector ; Size : natural ) return std_logic_vector is - begin - return std_logic_vector(to_unsigned(DistValInt(A, Exclude), Size)) ; - end function DistValSlv ; - - impure function DistValUnsigned ( A : DistType ; Exclude : integer_vector ; Size : natural ) return unsigned is - begin - return to_unsigned(DistValInt(A, Exclude), Size) ; - end function DistValUnsigned ; - - impure function DistValSigned ( A : DistType ; Exclude : integer_vector ; Size : natural ) return signed is - begin - return to_signed(DistValInt(A, Exclude), Size) ; - end function DistValSigned ; - - - -- - -- Large vector handling. - -- - impure function RandUnsigned (Size : natural) return unsigned is - constant NumLoops : integer := integer(ceil(real(Size)/30.0)) ; - constant Remain : integer := (Size - 1) mod 30 + 1 ; -- range 1 to 30 - variable RandVal : unsigned(1 to Size) ; - begin - if size = 0 then - return NULL_UV ; -- Null array - end if ; - for i in 0 to NumLoops-2 loop - RandVal(1 + 30*i to 30 + 30*i) := to_unsigned(RandInt(0, 2**30-1), 30) ; - end loop ; - RandVal(1+30*(NumLoops-1) to Remain + 30*(NumLoops-1)) := to_unsigned(RandInt(0, 2**Remain-1), Remain) ; - return RandVal ; - end function RandUnsigned ; - - impure function RandSlv (Size : natural) return std_logic_vector is - begin - return std_logic_vector(RandUnsigned(Size)) ; - end function RandSlv ; - - impure function RandSigned (Size : natural) return signed is - begin - return signed(RandUnsigned(Size)) ; - end function RandSigned ; - - - impure function RandUnsigned (Max : unsigned) return unsigned is - alias normMax : unsigned (Max'length downto 1) is Max ; - variable Result : unsigned(Max'range) := (others => '0') ; - alias normResult : unsigned(normMax'range) is Result ; - variable Size : integer ; - begin - -- Size = -1 if not found or Max'length = 0 - Size := find_leftmost(normMax, '1') ; - - if Size > 0 then - loop - normResult(Size downto 1) := RandUnsigned(Size) ; - exit when normResult <= Max ; - end loop ; - return Result ; -- = normResult with range same as Max - else - return resize("0", Max'length) ; - end if ; - end function RandUnsigned ; - - -- Working version that scales the value - -- impure function RandUnsigned (Max : unsigned) return unsigned is - -- constant MaxVal : unsigned(Max'length+3 downto 1) := (others => '1') ; - -- begin - -- if max'length > 0 then - -- -- "Max'length+3" creates 3 guard bits - -- return resize( RandUnsigned(Max'length+3) * ('0'&Max+1) / ('0'&MaxVal+1), Max'length) ; - -- else - -- return NULL_UV ; -- Null Array - -- end if ; - -- end function RandUnsigned ; - - impure function RandSlv (Max : std_logic_vector) return std_logic_vector is - begin - return std_logic_vector(RandUnsigned( unsigned(Max))) ; - end function RandSlv ; - - impure function RandSigned (Max : signed) return signed is - begin - if max'length > 0 then - assert (Max >= 0) report "%%RandomPkg RandSigned : Max < 0" severity FAILURE ; - return signed(RandUnsigned( unsigned(Max))) ; - else - return NULL_SV ; -- Null Array - end if ; - end function RandSigned ; - - - impure function RandUnsigned (Min, Max : unsigned) return unsigned is - constant LEN : integer := maximum(Max'length, Min'length) ; - begin - if LEN > 0 and Min <= Max then - return RandUnsigned(Max-Min) + Min ; - else - if Len > 0 then - report "%%RandomPkg RandUnsigned : Max < Min" severity FAILURE ; - end if ; - return NULL_UV ; - end if ; - end function RandUnsigned ; - - - impure function RandSlv (Min, Max : std_logic_vector) return std_logic_vector is - constant LEN : integer := maximum(Max'length, Min'length) ; - begin - if LEN > 0 and Min <= Max then - return RandSlv(Max-Min) + Min ; - else - if Len > 0 then - report "%%RandomPkg RandSlv : Max < Min" severity FAILURE ; - end if ; - return NULL_SlV ; - end if ; - end function RandSlv ; - - - impure function RandSigned (Min, Max : signed) return signed is - constant LEN : integer := maximum(Max'length, Min'length) ; - begin - if LEN > 0 and Min <= Max then - return resize(RandSigned(resize(Max,LEN+1) - resize(Min,LEN+1)) + Min, LEN) ; - else - if Len > 0 then - report "%%RandomPkg RandSigned : Max < Min" severity FAILURE ; - end if ; - return NULL_SV ; - end if ; - end function RandSigned ; - - - -- - -- Convenience Functions. Resolve into calls into the other functions - -- - impure function RandReal return real is - begin - return RandReal(0.0, 1.0) ; - end function RandReal ; - - impure function RandReal(Max : Real) return real is -- 0.0 to Max - begin - return RandReal(0.0, Max) ; - -- assert Max >= 0.0 report "RandReal : Range Error" severity FAILURE ; - -- return RandReal * Max ; - end function RandReal ; - - impure function RandInt (Max : integer) return integer is - begin - return RandInt(0, Max) ; - end function RandInt ; - - impure function RandSlv (Max, Size : natural) return std_logic_vector is - begin - return std_logic_vector(to_unsigned(RandInt(0, Max), Size)) ; - end function RandSlv ; - - impure function RandUnsigned (Max, Size : natural) return Unsigned is - begin - return to_unsigned(RandInt(0, Max), Size) ; - end function RandUnsigned ; - - - impure function RandSigned (Max : integer ; Size : natural ) return Signed is - begin - -- chose 0 to Max rather than -Max to +Max to be same as RandUnsigned, either seems logical - return to_signed(RandInt(0, Max), Size) ; - end function RandSigned ; - - end protected body RandomPType ; - +-- +-- File Name : RandomPkg.vhd +-- Design Unit Name : RandomPkg +-- Revision : STANDARD VERSION +-- +-- Maintainer : Jim Lewis email : jim@synthworks.com +-- Contributor(s) : +-- Jim Lewis email : jim@synthworks.com +-- * +-- +-- * In writing procedures normal, poisson, the following sources were referenced : +-- Wikipedia +-- package rnd2 written by John Breen and Ken Christensen +-- package RNG written by Gnanasekaran Swaminathan +-- +-- +-- Description : +-- RandomPType, a protected type, defined to hold randomization RandomSeeds and +-- function methods to facilitate randomization with uniform and weighted +-- distributions +-- +-- Developed for : +-- SynthWorks Design Inc. +-- VHDL Training Classes +-- 11898 SW 128th Ave. Tigard, Or 97223 +-- http ://www.SynthWorks.com +-- +-- Revision History : +-- Date Version Description +-- 12/2006 : 0.1 Initial revision +-- Numerous revisions for SynthWorks' Advanced VHDL Testbenches and Verification +-- 02/2009 : 1.0 First Public Released Version +-- 02/25/2009 1.1 Replaced reference to std_2008 with a reference to +-- ieee_proposed.standard_additions.all ; +-- 06/2010 1.2 Added Normal and Poisson distributions +-- 03/2011 2.0 Major clean-up. Moved RandomParmType and control to here +-- 07/2011 2.1 Bug fix to convenience functions for slv, unsigned, and signed. +-- 06/2012 2.2 Removed '_' in the name of subprograms FavorBig and FavorSmall +-- 04/2013 2013.04 Changed DistInt. Return array indices now match input +-- Better Min, Max error handling in Uniform, FavorBig, FavorSmall, Normal, Poisson +-- 5/2013 - Removed extra variable declaration in functions RandInt and RandReal +-- 5/2013 2013.05 Big vector randomization added overloading RandUnsigned, RandSlv, and RandSigned +-- Added NULL_RANGE_TYPE to minimize null range warnings +-- 1/2014 2014.01 Added RandTime, RandReal(set), RandIntV, RandRealV, RandTimeV +-- Made sort, revsort from SortListPkg_int visible via aliases +-- 1/2015 2015.01 Changed Assert/Report to Alert +-- 5/2015 2015.06 Revised Alerts to Alert(OSVVM_ALERTLOG_ID, ...) ; +-- 11/2016 2016.11 No changes. Updated release numbers to make documentation and +-- package have consistent release identifiers. +-- +-- Copyright (c) 2006 - 2016 by SynthWorks Design Inc. All rights reserved. +-- +-- Verbatim copies of this source file may be used and +-- distributed without restriction. +-- +-- This source file is free software ; you can redistribute it +-- and/or modify it under the terms of the ARTISTIC License +-- as published by The Perl Foundation ; either version 2.0 of +-- the License, or (at your option) any later version. +-- +-- This source is distributed in the hope that it will be +-- useful, but WITHOUT ANY WARRANTY ; without even the implied +-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +-- PURPOSE. See the Artistic License for details. +-- +-- You should have received a copy of the license with this source. +-- If not download it from, +-- http ://www.perlfoundation.org/artistic_license_2_0 +-- + +use work.OsvvmGlobalPkg.all ; +use work.AlertLogPkg.all ; +use work.RandomBasePkg.all ; +use work.SortListPkg_int.all ; + +use std.textio.all ; + +library ieee ; +use ieee.std_logic_1164.all ; +use ieee.numeric_std.all ; +use ieee.numeric_std_unsigned.all ; +use ieee.math_real.all ; + +-- comment out following 3 lines with VHDL-2008. Leave in for VHDL-2002 +-- library ieee_proposed ; -- remove with VHDL-2008 +-- use ieee_proposed.standard_additions.all ; -- remove with VHDL-2008 +-- use ieee_proposed.standard_textio_additions.all ; -- remove with VHDL-2008 + + +package RandomPkg is +-- Uncomment the following with VHDL-2008 package generics. +-- For now they are defined in the package RandomBasePkg.vhd +-- package RandomGenericPkg is + -- generic ( + -- type RandomSeedType ; -- base type for randomization + -- procedure Uniform (Result : out real ; Seed : inout RandomSeedType) ; + -- function GenRandSeed(IV : integer_vector) return RandomSeedType ; + -- function GenRandSeed(I : integer) return RandomSeedType ; + -- function GenRandSeed(S : string) return RandomSeedType ; + -- ) ; + + -- make things from SortListPkg_int visible + alias sort is work.SortListPkg_int.sort[integer_vector return integer_vector] ; + alias revsort is work.SortListPkg_int.revsort[integer_vector return integer_vector] ; + + -- note NULL_RANGE_TYPE should probably be in std.standard + subtype NULL_RANGE_TYPE is integer range 0 downto 1 ; + constant NULL_INTV : integer_vector (NULL_RANGE_TYPE) := (others => 0) ; + + -- Supports DistValInt functionality + type DistRecType is record + Value : integer ; + Weight : integer ; + end record ; + type DistType is array (natural range <>) of DistRecType ; + + + -- Parameters for randomization + -- RandomDistType specifies the distribution to use for randomize + type RandomDistType is (NONE, UNIFORM, FAVOR_SMALL, FAVOR_BIG, NORMAL, POISSON) ; + + type RandomParmType is record + Distribution : RandomDistType ; + Mean : Real ; -- also used as probability of success + StdDeviation : Real ; -- also used as number of trials for binomial + end record ; + + -- RandomParm IO + function to_string(A : RandomDistType) return string ; + procedure write(variable L : inout line ; A : RandomDistType ) ; + procedure read(variable L : inout line ; A : out RandomDistType ; good : out boolean ) ; + procedure read(variable L : inout line ; A : out RandomDistType ) ; + function to_string(A : RandomParmType) return string ; + procedure write(variable L : inout line ; A : RandomParmType ) ; + procedure read(variable L : inout line ; A : out RandomParmType ; good : out boolean ) ; + procedure read(variable L : inout line ; A : out RandomParmType ) ; + + + type RandomPType is protected + -- Seed Manipulation + -- Known ambiguity between InitSeed with string and integer_vector + -- Recommendation, use : RV.InitSeed(RV'instance_path) ; + -- For integer_vector use either : RV.InitSeed(IV => (1,5)) ; + -- or : RV.InitSeed(integer_vector'(1,5)) ; + procedure InitSeed (S : string ) ; + procedure InitSeed (I : integer ) ; + procedure InitSeed (IV : integer_vector ) ; + + -- SetSeed & GetSeed : Used to save and restore seed values + procedure SetSeed (RandomSeedIn : RandomSeedType ) ; + impure function GetSeed return RandomSeedType ; + -- SeedRandom = SetSeed & GetSeed for SV compatibility + -- replace with aliases when they work in popular simulators + procedure SeedRandom (RandomSeedIn : RandomSeedType ) ; + impure function SeedRandom return RandomSeedType ; + -- alias SeedRandom is SetSeed [RandomSeedType] ; + -- alias SeedRandom is GetSeed [return RandomSeedType] ; + + -- Setting Randomization Parameters + -- Allows RandInt to have distributions other than uniform + procedure SetRandomParm (RandomParmIn : RandomParmType) ; + procedure SetRandomParm ( + Distribution : RandomDistType ; + Mean : Real := 0.0 ; + Deviation : Real := 0.0 + ) ; + impure function GetRandomParm return RandomParmType ; + impure function GetRandomParm return RandomDistType ; + + -- For compatibility with previous version - replace with alias + procedure SetRandomMode (RandomDistIn : RandomDistType) ; + -- alias SetRandomMode is SetRandomParm [RandomDistType, Real, Real] ; + + -- Base Randomization Distributions + -- Uniform : Generate a random number with a Uniform distribution + impure function Uniform (Min, Max : in real) return real ; + impure function Uniform (Min, Max : integer) return integer ; + impure function Uniform (Min, Max : integer ; Exclude : integer_vector) return integer ; + + -- FavorSmall + -- Generate random numbers with a greater number of small + -- values than large values + impure function FavorSmall (Min, Max : real) return real ; + impure function FavorSmall (Min, Max : integer) return integer ; + impure function FavorSmall (Min, Max : integer ; Exclude : integer_vector) return integer ; + + -- FavorBig + -- Generate random numbers with a greater number of large + -- values than small values + impure function FavorBig (Min, Max : real) return real ; + impure function FavorBig (Min, Max : integer) return integer ; + impure function FavorBig (Min, Max : integer ; Exclude : integer_vector) return integer ; + + -- Normal : Generate a random number with a normal distribution + impure function Normal (Mean, StdDeviation : real) return real ; + -- Normal + RandomVal >= Min and RandomVal < Max + impure function Normal (Mean, StdDeviation, Min, Max : real) return real ; + impure function Normal ( + Mean : real ; + StdDeviation : real ; + Min : integer ; + Max : integer ; + Exclude : integer_vector := NULL_INTV + ) return integer ; + + -- Poisson : Generate a random number with a poisson distribution + -- Discrete distribution = only generates integral values + impure function Poisson (Mean : real) return real ; + -- Poisson + RandomVal >= Min and RandomVal < Max + impure function Poisson (Mean, Min, Max : real) return real ; + impure function Poisson ( + Mean : real ; + Min : integer ; + Max : integer ; + Exclude : integer_vector := NULL_INTV + ) return integer ; + + -- randomization with a range + impure function RandInt (Min, Max : integer) return integer ; + impure function RandReal(Min, Max : Real) return real ; + impure function RandTime (Min, Max : time ; Unit : time := ns) return time ; + impure function RandSlv (Min, Max, Size : natural) return std_logic_vector ; + impure function RandUnsigned (Min, Max, Size : natural) return Unsigned ; + impure function RandSigned (Min, Max : integer ; Size : natural ) return Signed ; + impure function RandIntV (Min, Max : integer ; Size : natural) return integer_vector ; + impure function RandIntV (Min, Max : integer ; Unique : natural ; Size : natural) return integer_vector ; + impure function RandRealV (Min, Max : real ; Size : natural) return real_vector ; + impure function RandTimeV (Min, Max : time ; Size : natural ; Unit : time := ns) return time_vector ; + impure function RandTimeV (Min, Max : time ; Unique : natural ; Size : natural ; Unit : time := ns) return time_vector ; + + -- randomization with a range and exclude vector + impure function RandInt (Min, Max : integer ; Exclude : integer_vector ) return integer ; + impure function RandTime (Min, Max : time ; Exclude : time_vector ; Unit : time := ns) return time ; + impure function RandSlv (Min, Max : natural ; Exclude : integer_vector ; Size : natural ) return std_logic_vector ; + impure function RandUnsigned (Min, Max : natural ; Exclude : integer_vector ; Size : natural ) return Unsigned ; + impure function RandSigned (Min, Max : integer ; Exclude : integer_vector ; Size : natural ) return Signed ; + impure function RandIntV (Min, Max : integer ; Exclude : integer_vector ; Size : natural) return integer_vector ; + impure function RandIntV (Min, Max : integer ; Exclude : integer_vector ; Unique : natural ; Size : natural) return integer_vector ; + impure function RandTimeV (Min, Max : time ; Exclude : time_vector ; Size : natural ; Unit : in time := ns) return time_vector ; + impure function RandTimeV (Min, Max : time ; Exclude : time_vector ; Unique : natural ; Size : natural ; Unit : in time := ns) return time_vector ; + + -- Randomly select a value within a set of values + impure function RandInt ( A : integer_vector ) return integer ; + impure function RandReal ( A : real_vector ) return real ; + impure function RandTime (A : time_vector) return time ; + impure function RandSlv (A : integer_vector ; Size : natural) return std_logic_vector ; + impure function RandUnsigned (A : integer_vector ; Size : natural) return Unsigned ; + impure function RandSigned (A : integer_vector ; Size : natural ) return Signed ; + impure function RandIntV (A : integer_vector ; Size : natural) return integer_vector ; + impure function RandIntV (A : integer_vector ; Unique : natural ; Size : natural) return integer_vector ; + impure function RandRealV (A : real_vector ; Size : natural) return real_vector ; + impure function RandRealV (A : real_vector ; Unique : natural ; Size : natural) return real_vector ; + impure function RandTimeV (A : time_vector ; Size : natural) return time_vector ; + impure function RandTimeV (A : time_vector ; Unique : natural ; Size : natural) return time_vector ; + + -- Randomly select a value within a set of values with exclude values (so can skip last or last n) + impure function RandInt ( A, Exclude : integer_vector ) return integer ; + impure function RandReal ( A, Exclude : real_vector ) return real ; + impure function RandTime (A, Exclude : time_vector) return time ; + impure function RandSlv (A, Exclude : integer_vector ; Size : natural) return std_logic_vector ; + impure function RandUnsigned (A, Exclude : integer_vector ; Size : natural) return Unsigned ; + impure function RandSigned (A, Exclude : integer_vector ; Size : natural ) return Signed ; + impure function RandIntV (A, Exclude : integer_vector ; Size : natural) return integer_vector ; + impure function RandIntV (A, Exclude : integer_vector ; Unique : natural ; Size : natural) return integer_vector ; + impure function RandRealV (A, Exclude : real_vector ; Size : natural) return real_vector ; + impure function RandRealV (A, Exclude : real_vector ; Unique : natural ; Size : natural) return real_vector ; + impure function RandTimeV (A, Exclude : time_vector ; Size : natural) return time_vector ; + impure function RandTimeV (A, Exclude : time_vector ; Unique : natural ; Size : natural) return time_vector ; + + -- Randomly select between 0 and N-1 based on the specified weight. + -- where N = number values in weight array + impure function DistInt ( Weight : integer_vector ) return integer ; + impure function DistSlv ( Weight : integer_vector ; Size : natural ) return std_logic_vector ; + impure function DistUnsigned ( Weight : integer_vector ; Size : natural ) return unsigned ; + impure function DistSigned ( Weight : integer_vector ; Size : natural ) return signed ; + + -- Distribution with just weights and with exclude values + impure function DistInt ( Weight : integer_vector ; Exclude : integer_vector ) return integer ; + impure function DistSlv ( Weight : integer_vector ; Exclude : integer_vector ; Size : natural ) return std_logic_vector ; + impure function DistUnsigned ( Weight : integer_vector ; Exclude : integer_vector ; Size : natural ) return unsigned ; + impure function DistSigned ( Weight : integer_vector ; Exclude : integer_vector ; Size : natural ) return signed ; + + -- Distribution with weight and value + impure function DistValInt ( A : DistType ) return integer ; + impure function DistValSlv ( A : DistType ; Size : natural) return std_logic_vector ; + impure function DistValUnsigned ( A : DistType ; Size : natural) return unsigned ; + impure function DistValSigned ( A : DistType ; Size : natural) return signed ; + + -- Distribution with weight and value and with exclude values + impure function DistValInt ( A : DistType ; Exclude : integer_vector ) return integer ; + impure function DistValSlv ( A : DistType ; Exclude : integer_vector ; Size : natural) return std_logic_vector ; + impure function DistValUnsigned ( A : DistType ; Exclude : integer_vector ; Size : natural) return unsigned ; + impure function DistValSigned ( A : DistType ; Exclude : integer_vector ; Size : natural) return signed ; + + -- Large vector handling. + impure function RandUnsigned (Size : natural) return unsigned ; + impure function RandSlv (Size : natural) return std_logic_vector ; + impure function RandSigned (Size : natural) return signed ; + impure function RandUnsigned (Max : Unsigned) return unsigned ; + impure function RandSlv (Max : std_logic_vector) return std_logic_vector ; + impure function RandSigned (Max : signed) return signed ; + impure function RandUnsigned (Min, Max : unsigned) return unsigned ; + impure function RandSlv (Min, Max : std_logic_vector) return std_logic_vector ; + impure function RandSigned (Min, Max : signed) return signed ; + + -- Convenience Functions + impure function RandReal return real ; -- 0.0 to 1.0 + impure function RandReal(Max : Real) return real ; -- 0.0 to Max + impure function RandInt (Max : integer) return integer ; + impure function RandSlv (Max, Size : natural) return std_logic_vector ; + impure function RandUnsigned (Max, Size : natural) return Unsigned ; + impure function RandSigned (Max : integer ; Size : natural ) return Signed ; + + end protected RandomPType ; + +end RandomPkg ; + +--- /////////////////////////////////////////////////////////////////////////// +--- /////////////////////////////////////////////////////////////////////////// +--- /////////////////////////////////////////////////////////////////////////// + +package body RandomPkg is + + ----------------------------------------------------------------- + -- Local Randomization Support + ----------------------------------------------------------------- + constant NULL_SLV : std_logic_vector (NULL_RANGE_TYPE) := (others => '0') ; + constant NULL_UV : unsigned (NULL_RANGE_TYPE) := (others => '0') ; + constant NULL_SV : signed (NULL_RANGE_TYPE) := (others => '0') ; + + ----------------------------------------------------------------- + -- Scale -- Scale a value to be within a given range + -- + function Scale (A, Min, Max : real) return real is + variable ValRange : Real ; + begin + if Max >= Min then + ValRange := Max - Min ; + return A * ValRange + Min ; + else + return real'left ; + end if ; + end function Scale ; + + function Scale (A : real ; Min, Max : integer) return integer is + variable ValRange : real ; + variable rMin, rMax : real ; + begin + if Max >= Min then + rMin := real(Min) - 0.5 ; + rMax := real(Max) + 0.5 ; + ValRange := rMax - rMin ; + return integer(round(A * ValRange + rMin)) ; + else + return integer'left ; + end if ; + end function Scale ; + + -- create more smaller values + function FavorSmall (A : real) return real is + begin + return 1.0 - sqrt(A) ; + end FavorSmall ; + + -- create more larger values + -- alias FavorBig is sqrt[real return real] ; + function FavorBig (A : real) return real is + begin + return sqrt(A) ; + end FavorBig ; + + -- local. + function to_time_vector (A : integer_vector ; Unit : time) return time_vector is + variable result : time_vector(A'range) ; + begin + for i in A'range loop + result(i) := A(i) * Unit ; + end loop ; + return result ; + end function to_time_vector ; + + -- local + function to_integer_vector (A : time_vector ; Unit : time) return integer_vector is + variable result : integer_vector(A'range) ; + begin + for i in A'range loop + result(i) := A(i) / Unit ; + end loop ; + return result ; + end function to_integer_vector ; + + -- Local. Remove the exclude list from the list - integer_vector + procedure RemoveExclude(A, Exclude : integer_vector ; variable NewA : out integer_vector ; variable NewALength : inout natural ) is + alias norm_NewA : integer_vector(1 to NewA'length) is NewA ; + begin + NewALength := 0 ; + for i in A'range loop + if not inside(A(i), Exclude) then + NewALength := NewALength + 1 ; + norm_NewA(NewALength) := A(i) ; + end if ; + end loop ; + end procedure RemoveExclude ; + + -- Local. Inside - real_vector + function inside(A : real ; Exclude : real_vector) return boolean is + begin + for i in Exclude'range loop + if A = Exclude(i) then + return TRUE ; + end if ; + end loop ; + return FALSE ; + end function inside ; + + -- Local. Remove the exclude list from the list - real_vector + procedure RemoveExclude(A, Exclude : real_vector ; variable NewA : out real_vector ; variable NewALength : inout natural ) is + alias norm_NewA : real_vector(1 to NewA'length) is NewA ; + begin + NewALength := 0 ; + for i in A'range loop + if not inside(A(i), Exclude) then + NewALength := NewALength + 1 ; + norm_NewA(NewALength) := A(i) ; + end if ; + end loop ; + end procedure RemoveExclude ; + + -- Local. Inside - time_vector + function inside(A : time ; Exclude : time_vector) return boolean is + begin + for i in Exclude'range loop + if A = Exclude(i) then + return TRUE ; + end if ; + end loop ; + return FALSE ; + end function inside ; + + -- Local. Remove the exclude list from the list - time_vector + procedure RemoveExclude(A, Exclude : time_vector ; variable NewA : out time_vector ; variable NewALength : inout natural ) is + alias norm_NewA : time_vector(1 to NewA'length) is NewA ; + begin + NewALength := 0 ; + for i in A'range loop + if not inside(A(i), Exclude) then + NewALength := NewALength + 1 ; + norm_NewA(NewALength) := A(i) ; + end if ; + end loop ; + end procedure RemoveExclude ; + + + ----------------------------------------------------------------- + -- RandomParmType IO + ----------------------------------------------------------------- + ----------------------------------------------------------------- + function to_string(A : RandomDistType) return string is + begin + return RandomDistType'image(A) ; + end function to_string ; + + + ----------------------------------------------------------------- + procedure write(variable L : inout line ; A : RandomDistType ) is + begin + write(L, to_string(A)) ; + end procedure write ; + + + ----------------------------------------------------------------- + procedure read(variable L : inout line ; A : out RandomDistType ; good : out boolean ) is + variable strval : string(1 to 40) ; + variable len : natural ; + begin + -- procedure SREAD (L : inout LINE ; VALUE : out STRING ; STRLEN : out NATURAL) ; + sread(L, strval, len) ; + A := RandomDistType'value(strval(1 to len)) ; + good := len > 0 ; + end procedure read ; + + + ----------------------------------------------------------------- + procedure read(variable L : inout line ; A : out RandomDistType ) is + variable ReadValid : boolean ; + begin + read(L, A, ReadValid) ; + AlertIfNot( OSVVM_ALERTLOG_ID, ReadValid, "RandomPkg.read[line, RandomDistType] failed", FAILURE) ; + end procedure read ; + + + ----------------------------------------------------------------- + function to_string(A : RandomParmType) return string is + begin + return RandomDistType'image(A.Distribution) & " " & + to_string(A.Mean, 2) & " " & to_string(A.StdDeviation, 2) ; + end function to_string ; + + + ----------------------------------------------------------------- + procedure write(variable L : inout line ; A : RandomParmType ) is + begin + write(L, to_string(A)) ; + end procedure write ; + + + ----------------------------------------------------------------- + procedure read(variable L : inout line ; A : out RandomParmType ; good : out boolean ) is + variable strval : string(1 to 40) ; + variable len : natural ; + variable igood : boolean ; + begin + loop + -- procedure SREAD (L : inout LINE ; VALUE : out STRING ; STRLEN : out NATURAL) ; + sread(L, strval, len) ; + A.Distribution := RandomDistType'value(strval(1 to len)) ; + igood := len > 0 ; + exit when not igood ; + + read(L, A.Mean, igood) ; + exit when not igood ; + + read(L, A.StdDeviation, igood) ; + exit ; + end loop ; + good := igood ; + end procedure read ; + + + ----------------------------------------------------------------- + procedure read(variable L : inout line ; A : out RandomParmType ) is + variable ReadValid : boolean ; + begin + read(L, A, ReadValid) ; + AlertIfNot( OSVVM_ALERTLOG_ID, ReadValid, "RandomPkg.read[line, RandomParmType] failed", FAILURE) ; + end procedure read ; + + + + ----------------------------------------------------------------- + ----------------------------------------------------------------- + type RandomPType is protected body + -- + -- RandomSeed manipulation + -- + variable RandomSeed : RandomSeedType := GenRandSeed(integer_vector'(1,7)) ; + + procedure InitSeed (S : string ) is + begin + RandomSeed := GenRandSeed(S) ; + end procedure InitSeed ; + + procedure InitSeed (I : integer ) is + begin + RandomSeed := GenRandSeed(I) ; + end procedure InitSeed ; + + procedure InitSeed (IV : integer_vector ) is + begin + RandomSeed := GenRandSeed(IV) ; + end procedure InitSeed ; + + procedure SetSeed (RandomSeedIn : RandomSeedType ) is + begin + RandomSeed := RandomSeedIn ; + end procedure SetSeed ; + + procedure SeedRandom (RandomSeedIn : RandomSeedType ) is + begin + RandomSeed := RandomSeedIn ; + end procedure SeedRandom ; + + impure function GetSeed return RandomSeedType is + begin + return RandomSeed ; + end function GetSeed ; + + impure function SeedRandom return RandomSeedType is + begin + return RandomSeed ; + end function SeedRandom ; + + + -- + -- randomization mode + -- + variable RandomParm : RandomParmType ; -- left most values ok for init + + procedure SetRandomParm (RandomParmIn : RandomParmType) is + begin + RandomParm := RandomParmIn ; + end procedure SetRandomParm ; + + procedure SetRandomParm ( + Distribution : RandomDistType ; + Mean : Real := 0.0 ; + Deviation : Real := 0.0 + ) is + begin + RandomParm := RandomParmType'(Distribution, Mean, Deviation) ; + end procedure SetRandomParm ; + + + impure function GetRandomParm return RandomParmType is + begin + return RandomParm ; + end function GetRandomParm ; + + + impure function GetRandomParm return RandomDistType is + begin + return RandomParm.Distribution ; + end function GetRandomParm ; + + + -- For compatibility with previous version + procedure SetRandomMode (RandomDistIn : RandomDistType) is + begin + SetRandomParm(RandomDistIn) ; + end procedure SetRandomMode ; + + + -- + -- Base Randomization Distributions + -- + -- + -- Uniform : Generate a random number with a Uniform distribution + -- + impure function Uniform (Min, Max : in real) return real is + variable rRandomVal : real ; + begin + AlertIf (OSVVM_ALERTLOG_ID, Max < Min, "RandomPkg.Uniform: Max < Min", FAILURE) ; + Uniform(rRandomVal, RandomSeed) ; + return scale(rRandomVal, Min, Max) ; + end function Uniform ; + + impure function Uniform (Min, Max : integer) return integer is + variable rRandomVal : real ; + begin + AlertIf (OSVVM_ALERTLOG_ID, Max < Min, "RandomPkg.Uniform: Max < Min", FAILURE) ; + Uniform(rRandomVal, RandomSeed) ; + return scale(rRandomVal, Min, Max) ; + end function Uniform ; + + impure function Uniform (Min, Max : integer ; Exclude : integer_vector) return integer is + variable iRandomVal : integer ; + variable ExcludeList : SortListPType ; + variable count : integer ; + begin + ExcludeList.add(Exclude, Min, Max) ; + count := ExcludeList.count ; + iRandomVal := Uniform(Min, Max - count) ; + -- adjust count, note iRandomVal changes while checking. + for i in 1 to count loop + exit when iRandomVal < ExcludeList.Get(i) ; + iRandomVal := iRandomVal + 1 ; + end loop ; + ExcludeList.erase ; + return iRandomVal ; + end function Uniform ; + + + -- + -- FavorSmall + -- Generate random numbers with a greater number of small + -- values than large values + -- + impure function FavorSmall (Min, Max : real) return real is + variable rRandomVal : real ; + begin + AlertIf (OSVVM_ALERTLOG_ID, Max < Min, "RandomPkg.FavorSmall: Max < Min", FAILURE) ; + Uniform(rRandomVal, RandomSeed) ; + return scale(FavorSmall(rRandomVal), Min, Max) ; -- real + end function FavorSmall ; + + impure function FavorSmall (Min, Max : integer) return integer is + variable rRandomVal : real ; + begin + AlertIf (OSVVM_ALERTLOG_ID, Max < Min, "RandomPkg.FavorSmall: Max < Min", FAILURE) ; + Uniform(rRandomVal, RandomSeed) ; + return scale(FavorSmall(rRandomVal), Min, Max) ; -- integer + end function FavorSmall ; + + impure function FavorSmall (Min, Max : integer ; Exclude : integer_vector) return integer is + variable iRandomVal : integer ; + variable ExcludeList : SortListPType ; + variable count : integer ; + begin + ExcludeList.add(Exclude, Min, Max) ; + count := ExcludeList.count ; + iRandomVal := FavorSmall(Min, Max - count) ; + -- adjust count, note iRandomVal changes while checking. + for i in 1 to count loop + exit when iRandomVal < ExcludeList.Get(i) ; + iRandomVal := iRandomVal + 1 ; + end loop ; + ExcludeList.erase ; + return iRandomVal ; + end function FavorSmall ; + + + -- + -- FavorBig + -- Generate random numbers with a greater number of large + -- values than small values + -- + impure function FavorBig (Min, Max : real) return real is + variable rRandomVal : real ; + begin + AlertIf (OSVVM_ALERTLOG_ID, Max < Min, "RandomPkg.FavorBig: Max < Min", FAILURE) ; + Uniform(rRandomVal, RandomSeed) ; + return scale(FavorBig(rRandomVal), Min, Max) ; -- real + end function FavorBig ; + + impure function FavorBig (Min, Max : integer) return integer is + variable rRandomVal : real ; + begin + AlertIf (OSVVM_ALERTLOG_ID, Max < Min, "RandomPkg.FavorBig: Max < Min", FAILURE) ; + Uniform(rRandomVal, RandomSeed) ; + return scale(FavorBig(rRandomVal), Min, Max) ; -- integer + end function FavorBig ; + + impure function FavorBig (Min, Max : integer ; Exclude : integer_vector) return integer is + variable iRandomVal : integer ; + variable ExcludeList : SortListPType ; + variable count : integer ; + begin + ExcludeList.add(Exclude, Min, Max) ; + count := ExcludeList.count ; + iRandomVal := FavorBig(Min, Max - count) ; + -- adjust count, note iRandomVal changes while checking. + for i in 1 to count loop + exit when iRandomVal < ExcludeList.Get(i) ; + iRandomVal := iRandomVal + 1 ; + end loop ; + ExcludeList.erase ; + return iRandomVal ; + end function FavorBig ; + + + ----------------------------------------------------------------- + -- Normal + -- Generate a random number with a normal distribution + -- + -- Use Box Muller, per Wikipedia : + -- http ://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform + -- + -- Use polar method, per Wikipedia : + -- http ://en.wikipedia.org/wiki/Marsaglia_polar_method + -- + impure function Normal (Mean, StdDeviation : real) return real is + variable x01, y01 : real ; + variable StdNormalDist : real ; -- mean 0, variance 1 + begin + -- add this check to set parameters? + if StdDeviation < 0.0 then + Alert(OSVVM_ALERTLOG_ID, "RandomPkg.Normal: Standard deviation must be >= 0.0", FAILURE) ; + return -1.0 ; + end if ; + + -- Box Muller + Uniform (x01, RandomSeed) ; + Uniform (y01, RandomSeed) ; + StdNormalDist := sqrt(-2.0 * log(x01)) * cos(math_2_pi*y01) ; + + -- Polar form rejected due to mean 50.0, std deviation = 5 resulted + -- in a median of 49 + -- -- find two Uniform distributed values with range -1 to 1 + -- -- that satisify S = X **2 + Y**2 < 1.0 + -- loop + -- Uniform (x01, RandomSeed) ; + -- Uniform (y01, RandomSeed) ; + -- x := 2.0 * x01 - 1.0 ; -- scale to -1 to 1 + -- y := 2.0 * y01 - 1.0 ; + -- s := x*x + y*y ; + -- exit when s < 1.0 and s > 0.0 ; + -- end loop ; + + -- -- Calculate Standard Normal Distribution + -- StdNormalDist := x * sqrt((-2.0 * log(s)) / s) ; + + -- Convert to have Mean and StdDeviation + return StdDeviation * StdNormalDist + Mean ; + end function Normal ; + + + -- Normal + RandomVal >= Min and RandomVal <= Max + impure function Normal (Mean, StdDeviation, Min, Max : real) return real is + variable rRandomVal : real ; + begin + if Max < Min then + Alert(OSVVM_ALERTLOG_ID, "RandomPkg.Normal: Max < Min", FAILURE) ; + return Mean ; + else + loop + rRandomVal := Normal (Mean, StdDeviation) ; + exit when rRandomVal >= Min and rRandomVal <= Max ; + end loop ; + end if ; + return rRandomVal ; + end function Normal ; + + -- Normal + RandomVal >= Min and RandomVal <= Max + impure function Normal ( + Mean : real ; + StdDeviation : real ; + Min : integer ; + Max : integer ; + Exclude : integer_vector := NULL_INTV + ) return integer is + variable iRandomVal : integer ; + begin + if Max < Min then + Alert(OSVVM_ALERTLOG_ID, "RandomPkg.Normal: Max < Min", FAILURE) ; + return integer(round(Mean)) ; + else + loop + iRandomVal := integer(round( Normal(Mean, StdDeviation) )) ; + exit when iRandomVal >= Min and iRandomVal <= Max and + not inside(iRandomVal, Exclude) ; + end loop ; + end if ; + return iRandomVal ; + end function Normal ; + + + ----------------------------------------------------------------- + -- Poisson + -- Generate a random number with a poisson distribution + -- Discrete distribution = only generates integral values + -- + -- Use knuth method, per Wikipedia : + -- http ://en.wikipedia.org/wiki/Poisson_distribution + -- + impure function Poisson (Mean : real) return real is + variable Product : Real := 1.0 ; + variable Bound : Real := 0.0 ; + variable UniformRand : Real := 0.0 ; + variable PoissonRand : Real := 0.0 ; + begin + Bound := exp(-1.0 * Mean) ; + Product := 1.0 ; + + -- add this check to set parameters? + if Mean <= 0.0 or Bound <= 0.0 then + Alert(OSVVM_ALERTLOG_ID, "RandomPkg.Poisson: Mean < 0 or too large. Mean = " & real'image(Mean), FAILURE) ; + return Mean ; + end if ; + + while (Product >= Bound) loop + PoissonRand := PoissonRand + 1.0 ; + Uniform(UniformRand, RandomSeed) ; + Product := Product * UniformRand ; + end loop ; + return PoissonRand ; + end function Poisson ; -- no range + + -- Poisson + RandomVal >= Min and RandomVal < Max + impure function Poisson (Mean, Min, Max : real) return real is + variable rRandomVal : real ; + begin + if Max < Min then + Alert(OSVVM_ALERTLOG_ID, "RandomPkg.Poisson: Max < Min", FAILURE) ; + return Mean ; + else + loop + rRandomVal := Poisson (Mean) ; + exit when rRandomVal >= Min and rRandomVal <= Max ; + end loop ; + end if ; + return rRandomVal ; + end function Poisson ; + + impure function Poisson ( + Mean : real ; + Min : integer ; + Max : integer ; + Exclude : integer_vector := NULL_INTV + ) return integer is + variable iRandomVal : integer ; + begin + if Max < Min then + Alert(OSVVM_ALERTLOG_ID, "RandomPkg.Poisson: Max < Min", FAILURE) ; + return integer(round(Mean)) ; + else + loop + iRandomVal := integer(round( Poisson (Mean) )) ; + exit when iRandomVal >= Min and iRandomVal <= Max and + not inside(iRandomVal, Exclude) ; + end loop ; + end if ; + return iRandomVal ; + end function Poisson ; + + + -- + -- integer randomization with a range + -- Distribution determined by RandomParm + -- + impure function RandInt (Min, Max : integer) return integer is + begin + case RandomParm.Distribution is + when NONE | UNIFORM => return Uniform(Min, Max) ; + when FAVOR_SMALL => return FavorSmall(Min, Max) ; + when FAVOR_BIG => return FavorBig (Min, Max) ; + when NORMAL => return Normal(RandomParm.Mean, RandomParm.StdDeviation, Min, Max) ; + when POISSON => return Poisson(RandomParm.Mean, Min, Max) ; + when others => + Alert(OSVVM_ALERTLOG_ID, "RandomPkg.RandInt: RandomParm.Distribution not implemented", FAILURE) ; + return integer'low ; + end case ; + end function RandInt ; + + -- + -- real randomization with a range + -- Distribution determined by RandomParm + -- + impure function RandReal(Min, Max : Real) return real is + begin + case RandomParm.Distribution is + when NONE | UNIFORM => return Uniform(Min, Max) ; + when FAVOR_SMALL => return FavorSmall(Min, Max) ; + when FAVOR_BIG => return FavorBig (Min, Max) ; + when NORMAL => return Normal(RandomParm.Mean, RandomParm.StdDeviation, Min, Max) ; + when POISSON => return Poisson(RandomParm.Mean, Min, Max) ; + when others => + Alert(OSVVM_ALERTLOG_ID, "RandomPkg.RandReal: Specified RandomParm.Distribution not implemented", FAILURE) ; + return real(integer'low) ; + end case ; + end function RandReal ; + + impure function RandTime (Min, Max : time ; Unit :time := ns) return time is + variable IntVal : integer ; + begin + -- if Max - Min > 2**31 result will be out of range + IntVal := RandInt(0, (Max - Min)/Unit) ; + Return Min + Unit*IntVal ; + end function RandTime ; + + impure function RandSlv (Min, Max, Size : natural) return std_logic_vector is + begin + return std_logic_vector(to_unsigned(RandInt(Min, Max), Size)) ; + end function RandSlv ; + + impure function RandUnsigned (Min, Max, Size : natural) return Unsigned is + begin + return to_unsigned(RandInt(Min, Max), Size) ; + end function RandUnsigned ; + + impure function RandSigned (Min, Max : integer ; Size : natural ) return Signed is + begin + return to_signed(RandInt(Min, Max), Size) ; + end function RandSigned ; + + impure function RandIntV (Min, Max : integer ; Size : natural) return integer_vector is + variable result : integer_vector(1 to Size) ; + begin + for i in result'range loop + result(i) := RandInt(Min, Max) ; + end loop ; + return result ; + end function RandIntV ; + + impure function RandIntV (Min, Max : integer ; Unique : natural ; Size : natural) return integer_vector is + variable result : integer_vector(1 to Size) ; + variable iUnique : natural ; + begin + -- if Unique = 0, it is more efficient to call RandIntV(Min, Max, Size) + iUnique := Unique ; + if Max-Min+1 < Unique then + Alert(OSVVM_ALERTLOG_ID, "RandomPkg.(RandIntV | RandRealV | RandTimeV): Unique > number of values available", FAILURE) ; + iUnique := Max-Min+1 ; + end if ; + for i in result'range loop + result(i) := RandInt(Min, Max, result(maximum(1, 1 + i - iUnique) to Size)) ; + end loop ; + return result ; + end function RandIntV ; + + impure function RandRealV (Min, Max : real ; Size : natural) return real_vector is + variable result : real_vector(1 to Size) ; + begin + for i in result'range loop + result(i) := RandReal(Min, Max) ; + end loop ; + return result ; + end function RandRealV ; + + impure function RandTimeV (Min, Max : time ; Size : natural ; Unit : time := ns) return time_vector is + variable result : time_vector(1 to Size) ; + begin + for i in result'range loop + result(i) := RandTime(Min, Max, Unit) ; + end loop ; + return result ; + end function RandTimeV ; + + impure function RandTimeV (Min, Max : time ; Unique : natural ; Size : natural ; Unit : time := ns) return time_vector is + begin + -- if Unique = 0, it is more efficient to call RandTimeV(Min, Max, Size) + return to_time_vector(RandIntV(Min/Unit, Max/Unit, Unique, Size), Unit) ; + end function RandTimeV ; + + + -- + -- integer randomization with a range and exclude vector + -- Distribution determined by RandomParm + -- + impure function RandInt (Min, Max : integer ; Exclude : integer_vector ) return integer is + begin + case RandomParm.Distribution is + when NONE | UNIFORM => return Uniform(Min, Max, Exclude) ; + when FAVOR_SMALL => return FavorSmall(Min, Max, Exclude) ; + when FAVOR_BIG => return FavorBig (Min, Max, Exclude) ; + when NORMAL => return Normal(RandomParm.Mean, RandomParm.StdDeviation, Min, Max, Exclude) ; + when POISSON => return Poisson(RandomParm.Mean, Min, Max, Exclude) ; + when others => + Alert(OSVVM_ALERTLOG_ID, "RandomPkg.RandInt: Specified RandomParm.Distribution not implemented", FAILURE) ; + return integer'low ; + end case ; + end function RandInt ; + + impure function RandTime (Min, Max : time ; Exclude : time_vector ; Unit : time := ns) return time is + variable IntVal : integer ; + begin + -- if Min or Max > 2**31 value will be out of range + return RandInt(Min/Unit, Max/Unit, to_integer_vector(Exclude, Unit)) * Unit ; + end function RandTime ; + + impure function RandSlv (Min, Max : natural ; Exclude : integer_vector ; Size : natural ) return std_logic_vector is + begin + return std_logic_vector(to_unsigned(RandInt(Min, Max, Exclude), Size)) ; + end function RandSlv ; + + impure function RandUnsigned (Min, Max : natural ; Exclude : integer_vector ; Size : natural ) return Unsigned is + begin + return to_unsigned(RandInt(Min, Max, Exclude), Size) ; + end function RandUnsigned ; + + impure function RandSigned (Min, Max : integer ; Exclude : integer_vector ; Size : natural ) return Signed is + begin + return to_signed(RandInt(Min, Max, Exclude), Size) ; + end function RandSigned ; + + impure function RandIntV (Min, Max : integer ; Exclude : integer_vector ; Size : natural) return integer_vector is + variable result : integer_vector(1 to Size) ; + begin + for i in result'range loop + result(i) := RandInt(Min, Max, Exclude) ; + end loop ; + return result ; + end function RandIntV ; + + impure function RandIntV (Min, Max : integer ; Exclude : integer_vector ; Unique : natural ; Size : natural) return integer_vector is + variable ResultPlus : integer_vector(1 to Size + Exclude'length) ; + begin + -- if Unique = 0, it is more efficient to call RandIntV(Min, Max, Size) + ResultPlus(Size+1 to ResultPlus'right) := Exclude ; + for i in 1 to Size loop + ResultPlus(i) := RandInt(Min, Max, ResultPlus(maximum(1, 1 + i - Unique) to ResultPlus'right)) ; + end loop ; + return ResultPlus(1 to Size) ; + end function RandIntV ; + + impure function RandTimeV (Min, Max : time ; Exclude : time_vector ; Size : natural ; Unit : in time := ns) return time_vector is + begin + return to_time_vector( RandIntV(Min/Unit, Max/Unit, to_integer_vector(Exclude, Unit), Size), Unit ) ; + end function RandTimeV ; + + impure function RandTimeV (Min, Max : time ; Exclude : time_vector ; Unique : natural ; Size : natural ; Unit : in time := ns) return time_vector is + begin + -- if Unique = 0, it is more efficient to call RandIntV(Min, Max, Size) + return to_time_vector( RandIntV(Min/Unit, Max/Unit, to_integer_vector(Exclude, Unit), Unique, Size), Unit ) ; + end function RandTimeV ; + + + + -- + -- Randomly select a value within a set of values + -- Distribution determined by RandomParm + -- + impure function RandInt ( A : integer_vector ) return integer is + alias A_norm : integer_vector(1 to A'length) is A ; + begin + return A_norm( RandInt(1, A'length) ) ; + end function RandInt ; + + impure function RandReal ( A : real_vector ) return real is + alias A_norm : real_vector(1 to A'length) is A ; + begin + return A_norm( RandInt(1, A'length) ) ; + end function RandReal ; + + impure function RandTime ( A : time_vector ) return time is + alias A_norm : time_vector(1 to A'length) is A ; + begin + return A_norm( RandInt(1, A'length) ) ; + end function RandTime ; + + impure function RandSlv (A : integer_vector ; Size : natural) return std_logic_vector is + begin + return std_logic_vector(to_unsigned(RandInt(A), Size)) ; + end function RandSlv ; + + impure function RandUnsigned (A : integer_vector ; Size : natural) return Unsigned is + begin + return to_unsigned(RandInt(A), Size) ; + end function RandUnsigned ; + + impure function RandSigned (A : integer_vector ; Size : natural ) return Signed is + begin + return to_signed(RandInt(A), Size) ; + end function RandSigned ; + + impure function RandIntV (A : integer_vector ; Size : natural) return integer_vector is + variable result : integer_vector(1 to Size) ; + begin + for i in result'range loop + result(i) := RandInt(A) ; + end loop ; + return result ; + end function RandIntV ; + + impure function RandIntV (A : integer_vector ; Unique : natural ; Size : natural) return integer_vector is + variable result : integer_vector(1 to Size) ; + variable iUnique : natural ; + begin + -- if Unique = 0, it is more efficient to call RandIntV(A, Size) + -- require A'length >= Unique + iUnique := Unique ; + if A'length < Unique then + Alert(OSVVM_ALERTLOG_ID, "RandomPkg.RandIntV: Unique > length of set of values", FAILURE) ; + iUnique := A'length ; + end if ; + for i in result'range loop + result(i) := RandInt(A, result(maximum(1, 1 + i - iUnique) to Size)) ; + end loop ; + return result ; + end function RandIntV ; + + impure function RandRealV (A : real_vector ; Size : natural) return real_vector is + variable result : real_vector(1 to Size) ; + begin + for i in result'range loop + result(i) := RandReal(A) ; + end loop ; + return result ; + end function RandRealV ; + + impure function RandRealV (A : real_vector ; Unique : natural ; Size : natural) return real_vector is + alias A_norm : real_vector(1 to A'length) is A ; + variable result : real_vector(1 to Size) ; + variable IntResult : integer_vector(result'range) ; + begin + -- randomly generate indices + IntResult := RandIntV(1, A'length, Unique, Size) ; + -- translate indicies into result values + for i in result'range loop + result(i) := A_norm(IntResult(i)) ; + end loop ; + return result ; + end function RandRealV ; + + impure function RandTimeV (A : time_vector ; Size : natural) return time_vector is + variable result : time_vector(1 to Size) ; + begin + for i in result'range loop + result(i) := RandTime(A) ; + end loop ; + return result ; + end function RandTimeV ; + + impure function RandTimeV (A : time_vector ; Unique : natural ; Size : natural) return time_vector is + alias A_norm : time_vector(1 to A'length) is A ; + variable result : time_vector(1 to Size) ; + variable IntResult : integer_vector(result'range) ; + begin + -- randomly generate indices + IntResult := RandIntV(1, A'length, Unique, Size) ; + -- translate indicies into result values + for i in result'range loop + result(i) := A_norm(IntResult(i)) ; + end loop ; + return result ; + end function RandTimeV ; + + + -- + -- Randomly select a value within a set of values with exclude values (so can skip last or last n) + -- Distribution determined by RandomParm + -- + + impure function RandInt ( A, Exclude : integer_vector ) return integer is + variable NewA : integer_vector(1 to A'length) ; + variable NewALength : natural ; + begin + -- Remove Exclude from A + RemoveExclude(A, Exclude, NewA, NewALength) ; + -- Randomize Index + return NewA(RandInt(1, NewALength)) ; + end function RandInt ; + + impure function RandReal ( A, Exclude : real_vector ) return real is + variable NewA : real_vector(1 to A'length) ; + variable NewALength : natural ; + begin + -- Remove Exclude from A + RemoveExclude(A, Exclude, NewA, NewALength) ; + -- Randomize Index + return NewA(RandInt(1, NewALength)) ; + end function RandReal ; + + impure function RandTime ( A, Exclude : time_vector ) return time is + variable NewA : time_vector(1 to A'length) ; + variable NewALength : natural ; + begin + -- Remove Exclude from A + RemoveExclude(A, Exclude, NewA, NewALength) ; + -- Randomize Index + return NewA(RandInt(1, NewALength)) ; + end function RandTime ; + + impure function RandSlv (A, Exclude : integer_vector ; Size : natural) return std_logic_vector is + begin + return std_logic_vector(to_unsigned(RandInt(A, Exclude), Size)) ; + end function RandSlv ; + + impure function RandUnsigned (A, Exclude : integer_vector ; Size : natural) return Unsigned is + begin + return to_unsigned(RandInt(A, Exclude), Size) ; + end function RandUnsigned ; + + impure function RandSigned (A, Exclude : integer_vector ; Size : natural ) return Signed is + begin + return to_signed(RandInt(A, Exclude), Size) ; + end function RandSigned ; + + impure function RandIntV (A, Exclude : integer_vector ; Size : natural) return integer_vector is + variable result : integer_vector(1 to Size) ; + variable NewA : integer_vector(1 to A'length) ; + variable NewALength : natural ; + begin + -- Remove Exclude from A + RemoveExclude(A, Exclude, NewA, NewALength) ; + -- Randomize Index + for i in result'range loop + result(i) := NewA(RandInt(1, NewALength)) ; + end loop ; + return result ; + end function RandIntV ; + + impure function RandIntV (A, Exclude : integer_vector ; Unique : natural ; Size : natural) return integer_vector is + variable result : integer_vector(1 to Size) ; + variable NewA : integer_vector(1 to A'length) ; + variable NewALength, iUnique : natural ; + begin + -- if Unique = 0, it is more efficient to call RandIntV(Min, Max, Size) + -- Remove Exclude from A + RemoveExclude(A, Exclude, NewA, NewALength) ; + -- Require NewALength >= Unique + iUnique := Unique ; + if NewALength < Unique then + Alert(OSVVM_ALERTLOG_ID, "RandomPkg.RandIntV: Unique > Length of Set A - Exclude", FAILURE) ; + iUnique := NewALength ; + end if ; + -- Randomize using exclude list of Unique # of newly generated values + for i in result'range loop + result(i) := RandInt(NewA(1 to NewALength), result(maximum(1, 1 + i - iUnique) to Size)) ; + end loop ; + return result ; + end function RandIntV ; + + impure function RandRealV (A, Exclude : real_vector ; Size : natural) return real_vector is + variable result : real_vector(1 to Size) ; + variable NewA : real_vector(1 to A'length) ; + variable NewALength : natural ; + begin + -- Remove Exclude from A + RemoveExclude(A, Exclude, NewA, NewALength) ; + -- Randomize Index + for i in result'range loop + result(i) := NewA(RandInt(1, NewALength)) ; + end loop ; + return result ; + end function RandRealV ; + + impure function RandRealV (A, Exclude : real_vector ; Unique : natural ; Size : natural) return real_vector is + variable result : real_vector(1 to Size) ; + variable NewA : real_vector(1 to A'length) ; + variable NewALength, iUnique : natural ; + begin + -- if Unique = 0, it is more efficient to call RandRealV(Min, Max, Size) + -- Remove Exclude from A + RemoveExclude(A, Exclude, NewA, NewALength) ; + -- Require NewALength >= Unique + iUnique := Unique ; + if NewALength < Unique then + Alert(OSVVM_ALERTLOG_ID, "RandomPkg.RandRealV: Unique > Length of Set A - Exclude", FAILURE) ; + iUnique := NewALength ; + end if ; + -- Randomize using exclude list of Unique # of newly generated values + for i in result'range loop + result(i) := RandReal(NewA(1 to NewALength), result(maximum(1, 1 + i - iUnique) to Size)) ; + end loop ; + return result ; + end function RandRealV ; + + impure function RandTimeV (A, Exclude : time_vector ; Size : natural) return time_vector is + variable result : time_vector(1 to Size) ; + variable NewA : time_vector(1 to A'length) ; + variable NewALength : natural ; + begin + -- Remove Exclude from A + RemoveExclude(A, Exclude, NewA, NewALength) ; + -- Randomize Index + for i in result'range loop + result(i) := NewA(RandInt(1, NewALength)) ; + end loop ; + return result ; + end function RandTimeV ; + + impure function RandTimeV (A, Exclude : time_vector ; Unique : natural ; Size : natural) return time_vector is + variable result : time_vector(1 to Size) ; + variable NewA : time_vector(1 to A'length) ; + variable NewALength, iUnique : natural ; + begin + -- if Unique = 0, it is more efficient to call RandRealV(Min, Max, Size) + -- Remove Exclude from A + RemoveExclude(A, Exclude, NewA, NewALength) ; + -- Require NewALength >= Unique + iUnique := Unique ; + if NewALength < Unique then + Alert(OSVVM_ALERTLOG_ID, "RandomPkg.RandTimeV: Unique > Length of Set A - Exclude", FAILURE) ; + iUnique := NewALength ; + end if ; + -- Randomize using exclude list of Unique # of newly generated values + for i in result'range loop + result(i) := RandTime(NewA(1 to NewALength), result(maximum(1, 1 + i - iUnique) to Size)) ; + end loop ; + return result ; + end function RandTimeV ; + + + -- + -- Basic Discrete Distributions + -- Always uses Uniform + -- + impure function DistInt ( Weight : integer_vector ) return integer is + variable DistArray : integer_vector(weight'range) ; + variable sum : integer ; + variable iRandomVal : integer ; + begin + DistArray := Weight ; + sum := 0 ; + for i in DistArray'range loop + DistArray(i) := DistArray(i) + sum ; + if DistArray(i) < sum then + Alert(OSVVM_ALERTLOG_ID, "RandomPkg.DistInt: negative weight or sum > 31 bits", FAILURE) ; + return DistArray'low ; -- allows debugging vs integer'left, out of range + end if ; + sum := DistArray(i) ; + end loop ; + if sum >= 1 then + iRandomVal := Uniform(1, sum) ; + for i in DistArray'range loop + if iRandomVal <= DistArray(i) then + return i ; + end if ; + end loop ; + Alert(OSVVM_ALERTLOG_ID, "RandomPkg.DistInt: randomization failed", FAILURE) ; + else + Alert(OSVVM_ALERTLOG_ID, "RandomPkg.DistInt: No randomization weights", FAILURE) ; + end if ; + return DistArray'low ; -- allows debugging vs integer'left, out of range + end function DistInt ; + + impure function DistSlv ( Weight : integer_vector ; Size : natural ) return std_logic_vector is + begin + return std_logic_vector(to_unsigned(DistInt(Weight), Size)) ; + end function DistSlv ; + + impure function DistUnsigned ( Weight : integer_vector ; Size : natural ) return unsigned is + begin + return to_unsigned(DistInt(Weight), Size) ; + end function DistUnsigned ; + + impure function DistSigned ( Weight : integer_vector ; Size : natural ) return signed is + begin + return to_signed(DistInt(Weight), Size) ; + end function DistSigned ; + + + -- + -- Basic Distributions with exclude values (so can skip last or last n) + -- Always uses Uniform via DistInt + -- + impure function DistInt ( Weight : integer_vector ; Exclude : integer_vector ) return integer is + variable DistArray : integer_vector(weight'range) ; + variable ExcludeTemp : integer ; + begin + DistArray := Weight ; + for i in Exclude'range loop + ExcludeTemp := Exclude(i) ; + if ExcludeTemp >= DistArray'low and ExcludeTemp <= DistArray'high then + DistArray(ExcludeTemp) := 0 ; + end if ; + end loop ; + return DistInt(DistArray) ; + end function DistInt ; + + impure function DistSlv ( Weight : integer_vector ; Exclude : integer_vector ; Size : natural ) return std_logic_vector is + begin + return std_logic_vector(to_unsigned(DistInt(Weight, Exclude), Size)) ; + end function DistSlv ; + + impure function DistUnsigned ( Weight : integer_vector ; Exclude : integer_vector ; Size : natural ) return unsigned is + begin + return to_unsigned(DistInt(Weight, Exclude), Size) ; + end function DistUnsigned ; + + impure function DistSigned ( Weight : integer_vector ; Exclude : integer_vector ; Size : natural ) return signed is + begin + return to_signed(DistInt(Weight, Exclude), Size) ; + end function DistSigned ; + + + -- + -- Distribution for sparse values + -- Always uses Uniform via DistInt + -- + impure function DistValInt ( A : DistType ) return integer is + variable DistArray : integer_vector(0 to A'length -1) ; + alias DistRecArray : DistType(DistArray'range) is A ; + begin + for i in DistArray'range loop + DistArray(i) := DistRecArray(i).Weight ; + end loop ; + return DistRecArray(DistInt(DistArray)).Value ; + end function DistValInt ; + + impure function DistValSlv ( A : DistType ; Size : natural ) return std_logic_vector is + begin + return std_logic_vector(to_unsigned(DistValInt(A), Size)) ; + end function DistValSlv ; + + impure function DistValUnsigned ( A : DistType ; Size : natural ) return unsigned is + begin + return to_unsigned(DistValInt(A), Size) ; + end function DistValUnsigned ; + + impure function DistValSigned ( A : DistType ; Size : natural ) return signed is + begin + return to_signed(DistValInt(A), Size) ; + end function DistValSigned ; + + + -- + -- Distribution for sparse values with exclude values (so can skip last or last n) + -- Always uses Uniform via DistInt + -- + impure function DistValInt ( A : DistType ; Exclude : integer_vector ) return integer is + variable DistArray : integer_vector(0 to A'length -1) ; + alias DistRecArray : DistType(DistArray'range) is A ; + begin + for i in DistRecArray'range loop + if inside(DistRecArray(i).Value, exclude) then + DistArray(i) := 0 ; -- exclude + else + DistArray(i) := DistRecArray(i).Weight ; + end if ; + end loop ; + return DistRecArray(DistInt(DistArray)).Value ; + end function DistValInt ; + + impure function DistValSlv ( A : DistType ; Exclude : integer_vector ; Size : natural ) return std_logic_vector is + begin + return std_logic_vector(to_unsigned(DistValInt(A, Exclude), Size)) ; + end function DistValSlv ; + + impure function DistValUnsigned ( A : DistType ; Exclude : integer_vector ; Size : natural ) return unsigned is + begin + return to_unsigned(DistValInt(A, Exclude), Size) ; + end function DistValUnsigned ; + + impure function DistValSigned ( A : DistType ; Exclude : integer_vector ; Size : natural ) return signed is + begin + return to_signed(DistValInt(A, Exclude), Size) ; + end function DistValSigned ; + + + -- + -- Large vector handling. + -- + impure function RandUnsigned (Size : natural) return unsigned is + constant NumLoops : integer := integer(ceil(real(Size)/30.0)) ; + constant Remain : integer := (Size - 1) mod 30 + 1 ; -- range 1 to 30 + variable RandVal : unsigned(1 to Size) ; + begin + if size = 0 then + return NULL_UV ; -- Null array + end if ; + for i in 0 to NumLoops-2 loop + RandVal(1 + 30*i to 30 + 30*i) := to_unsigned(RandInt(0, 2**30-1), 30) ; + end loop ; + RandVal(1+30*(NumLoops-1) to Remain + 30*(NumLoops-1)) := to_unsigned(RandInt(0, 2**Remain-1), Remain) ; + return RandVal ; + end function RandUnsigned ; + + impure function RandSlv (Size : natural) return std_logic_vector is + begin + return std_logic_vector(RandUnsigned(Size)) ; + end function RandSlv ; + + impure function RandSigned (Size : natural) return signed is + begin + return signed(RandUnsigned(Size)) ; + end function RandSigned ; + + + impure function RandUnsigned (Max : unsigned) return unsigned is + alias normMax : unsigned (Max'length downto 1) is Max ; + variable Result : unsigned(Max'range) := (others => '0') ; + alias normResult : unsigned(normMax'range) is Result ; + variable Size : integer ; + begin + -- Size = -1 if not found or Max'length = 0 + Size := find_leftmost(normMax, '1') ; + + if Size > 0 then + loop + normResult(Size downto 1) := RandUnsigned(Size) ; + exit when normResult <= Max ; + end loop ; + return Result ; -- = normResult with range same as Max + else + return resize("0", Max'length) ; + end if ; + end function RandUnsigned ; + + -- Working version that scales the value + -- impure function RandUnsigned (Max : unsigned) return unsigned is + -- constant MaxVal : unsigned(Max'length+3 downto 1) := (others => '1') ; + -- begin + -- if max'length > 0 then + -- -- "Max'length+3" creates 3 guard bits + -- return resize( RandUnsigned(Max'length+3) * ('0'&Max+1) / ('0'&MaxVal+1), Max'length) ; + -- else + -- return NULL_UV ; -- Null Array + -- end if ; + -- end function RandUnsigned ; + + impure function RandSlv (Max : std_logic_vector) return std_logic_vector is + begin + return std_logic_vector(RandUnsigned( unsigned(Max))) ; + end function RandSlv ; + + impure function RandSigned (Max : signed) return signed is + begin + if max'length > 0 then + AlertIf (OSVVM_ALERTLOG_ID, Max < 0, "RandomPkg.RandSigned: Max < 0", FAILURE) ; + return signed(RandUnsigned( unsigned(Max))) ; + else + return NULL_SV ; -- Null Array + end if ; + end function RandSigned ; + + + impure function RandUnsigned (Min, Max : unsigned) return unsigned is + constant LEN : integer := maximum(Max'length, Min'length) ; + begin + if LEN > 0 and Min <= Max then + return RandUnsigned(Max-Min) + Min ; + else + if Len > 0 then + Alert(OSVVM_ALERTLOG_ID, "RandomPkg.RandUnsigned: Max < Min", FAILURE) ; + end if ; + return NULL_UV ; + end if ; + end function RandUnsigned ; + + + impure function RandSlv (Min, Max : std_logic_vector) return std_logic_vector is + constant LEN : integer := maximum(Max'length, Min'length) ; + begin + if LEN > 0 and Min <= Max then + return RandSlv(Max-Min) + Min ; + else + if Len > 0 then + Alert(OSVVM_ALERTLOG_ID, "RandomPkg.RandSlv: Max < Min", FAILURE) ; + end if ; + return NULL_SlV ; + end if ; + end function RandSlv ; + + + impure function RandSigned (Min, Max : signed) return signed is + constant LEN : integer := maximum(Max'length, Min'length) ; + begin + if LEN > 0 and Min <= Max then + return resize(RandSigned(resize(Max,LEN+1) - resize(Min,LEN+1)) + Min, LEN) ; + else + if Len > 0 then + Alert(OSVVM_ALERTLOG_ID, "RandomPkg.RandSigned: Max < Min", FAILURE) ; + end if ; + return NULL_SV ; + end if ; + end function RandSigned ; + + + -- + -- Convenience Functions. Resolve into calls into the other functions + -- + impure function RandReal return real is + begin + return RandReal(0.0, 1.0) ; + end function RandReal ; + + impure function RandReal(Max : Real) return real is -- 0.0 to Max + begin + return RandReal(0.0, Max) ; + end function RandReal ; + + impure function RandInt (Max : integer) return integer is + begin + return RandInt(0, Max) ; + end function RandInt ; + + impure function RandSlv (Max, Size : natural) return std_logic_vector is + begin + return std_logic_vector(to_unsigned(RandInt(0, Max), Size)) ; + end function RandSlv ; + + impure function RandUnsigned (Max, Size : natural) return Unsigned is + begin + return to_unsigned(RandInt(0, Max), Size) ; + end function RandUnsigned ; + + + impure function RandSigned (Max : integer ; Size : natural ) return Signed is + begin + -- chose 0 to Max rather than -Max to +Max to be same as RandUnsigned, either seems logical + return to_signed(RandInt(0, Max), Size) ; + end function RandSigned ; + + end protected body RandomPType ; + end RandomPkg ; \ No newline at end of file diff --git a/OSVVM/ResolutionPkg.vhd b/OSVVM/ResolutionPkg.vhd new file mode 100644 index 0000000..9fccbf2 --- /dev/null +++ b/OSVVM/ResolutionPkg.vhd @@ -0,0 +1,392 @@ +-- +-- File Name: ResolutionPkg.vhd +-- Design Unit Name: ResolutionPkg +-- Revision: STANDARD VERSION +-- +-- Maintainer: Jim Lewis email: jim@SynthWorks.com +-- Contributor(s): +-- Jim Lewis email: jim@SynthWorks.com +-- +-- Package Defines +-- resolved resolution functions for integer, real, and time +-- types resolved_integer, resolved_real, resolved_time +-- +-- Developed for: +-- SynthWorks Design Inc. +-- VHDL Training Classes +-- 11898 SW 128th Ave. Tigard, Or 97223 +-- http://www.SynthWorks.com +-- +-- Revision History: +-- Date Version Description +-- 09/2006: 0.1 Initial revision +-- Numerous revisions for VHDL Testbenches and Verification +-- 02/2009: 1.0 VHDL-2008 STANDARD VERSION +-- 05/2015 2015.05 Added Alerts +-- -- Replaced Alerts with asserts as alerts are illegal in pure functions +-- 11/2016 2016.11 Removed Asserts as they are not working as intended. +-- See ResolutionPkg_debug as it uses Alerts to correctly detect errors +-- +-- +-- Copyright (c) 2005 - 2016 by SynthWorks Design Inc. All rights reserved. +-- +-- Verbatim copies of this source file may be used and +-- distributed without restriction. +-- +-- This source file may be modified and distributed under +-- the terms of the ARTISTIC License as published by +-- The Perl Foundation; either version 2.0 of the License, +-- or (at your option) any later version. +-- +-- This source is distributed in the hope that it will be +-- useful, but WITHOUT ANY WARRANTY; without even the implied +-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +-- PURPOSE. See the Artistic License for details. +-- +-- You should have received a copy of the license with this source. +-- If not download it from, +-- http://www.perlfoundation.org/artistic_license_2_0 +-- + +library ieee ; +use ieee.std_logic_1164.all ; +use ieee.numeric_std.all ; + +library osvvm ; +use osvvm.AlertLogPkg.all ; + +package ResolutionPkg is + constant MULTIPLE_DRIVER_SEVERITY : severity_level := ERROR ; + +-- +-- Note that not all simulators support resolution functions of the form: +-- subtype std_logic_vector_max is (resolved_max) std_ulogic_vector ; +-- +-- Hence, types of the form are offered as a temporary workaround until they do: +-- std_logic_vector_max_c is array (natural range <>) of std_logic_max ; -- for non VHDL-2008 +-- + + -- resolved_max + -- return maximum value. + -- No initializations required on ports, default of type'left is ok + function resolved_max ( s : std_ulogic_vector) return std_ulogic ; + subtype std_logic_max is resolved_max std_ulogic ; + subtype std_logic_vector_max is (resolved_max) std_ulogic_vector ; + type std_logic_vector_max_c is array (natural range <>) of std_logic_max ; -- for non VHDL-2008 + + subtype unsigned_max is (resolved_max) unresolved_unsigned ; + type unsigned_max_c is array (natural range <>) of std_logic_max ; -- for non VHDL-2008 + subtype signed_max is (resolved_max) unresolved_signed ; + type signed_max_c is array (natural range <>) of std_logic_max ; -- for non VHDL-2008 + + function resolved_max ( s : bit_vector) return bit ; + subtype bit_max is resolved_max bit ; + subtype bit_vector_max is (resolved_max) bit_vector ; + type bit_vector_max_c is array (natural range <>) of bit_max ; -- for non VHDL-2008 + + function resolved_max ( s : integer_vector ) return integer ; + subtype integer_max is resolved_max integer ; + subtype integer_vector_max is (resolved_max) integer_vector ; + type integer_vector_max_c is array (natural range <>) of integer_max ; -- for non VHDL-2008 + + function resolved_max ( s : time_vector ) return time ; + subtype time_max is resolved_max time ; + subtype time_vector_max is (resolved_max) time_vector ; + type time_vector_max_c is array (natural range <>) of time_max ; -- for non VHDL-2008 + + function resolved_max ( s : real_vector ) return real ; + subtype real_max is resolved_max real ; + subtype real_vector_max is (resolved_max) real_vector ; + type real_vector_max_c is array (natural range <>) of real_max ; -- for non VHDL-2008 + + function resolved_max ( s : string) return character ; + subtype character_max is resolved_max character ; + subtype string_max is (resolved_max) string ; + type string_max_c is array (positive range <>) of character_max ; -- for non VHDL-2008 + + function resolved_max ( s : boolean_vector) return boolean ; + subtype boolean_max is resolved_max boolean ; + subtype boolean_vector_max is (resolved_max) boolean_vector ; + type boolean_vector_max_c is array (natural range <>) of boolean_max ; -- for non VHDL-2008 + + + -- return sum of values that /= type'left + -- No initializations required on ports, default of type'left is ok + function resolved_sum ( s : integer_vector ) return integer ; + subtype integer_sum is resolved_sum integer ; + subtype integer_vector_sum is (resolved_sum) integer_vector ; + type integer_vector_sum_c is array (natural range <>) of integer_sum ; -- for non VHDL-2008 + + function resolved_sum ( s : time_vector ) return time ; + subtype time_sum is resolved_sum time ; + subtype time_vector_sum is (resolved_sum) time_vector ; + type time_vector_sum_c is array (natural range <>) of time_sum ; -- for non VHDL-2008 + + function resolved_sum ( s : real_vector ) return real ; + subtype real_sum is resolved_sum real ; + subtype real_vector_sum is (resolved_sum) real_vector ; + type real_vector_sum_c is array (natural range <>) of real_sum ; -- for non VHDL-2008 + + + -- resolved_weak + -- Special just for std_ulogic + -- No initializations required on ports, default of type'left is ok + function resolved_weak (s : std_ulogic_vector) return std_ulogic ; -- no init, type'left + subtype std_logic_weak is resolved_weak std_ulogic ; + subtype std_logic_vector_weak is (resolved_weak) std_ulogic_vector ; + + + -- legacy stuff + -- requires ports to be initialized to 0 in the appropriate type. + function resolved ( s : integer_vector ) return integer ; + subtype resolved_integer is resolved integer ; + + function resolved ( s : time_vector ) return time ; + subtype resolved_time is resolved time ; + + function resolved ( s : real_vector ) return real ; + subtype resolved_real is resolved real ; + + function resolved (s : string) return character ; -- same as resolved_max + subtype resolved_character is resolved character ; + -- subtype resolved_string is (resolved) string ; -- subtype will replace type later + type resolved_string is array (positive range <>) of resolved_character; -- will change to subtype -- assert but no init + + function resolved ( s : boolean_vector) return boolean ; --same as resolved_max + subtype resolved_boolean is resolved boolean ; + +end package ResolutionPkg ; +package body ResolutionPkg is + + -- resolved_max + -- return maximum value. Assert FAILURE if more than 1 /= type'left + -- No initializations required on ports, default of type'left is ok + + -- Optimized version is just the following: + -- ------------------------------------------------------------ + -- function resolved_max ( s : ) return is + -- ------------------------------------------------------------ + -- begin + -- return maximum(s) ; + -- end function resolved_max ; + + ------------------------------------------------------------ + function resolved_max (s : std_ulogic_vector) return std_ulogic is + ------------------------------------------------------------ + begin + return maximum(s) ; + end function resolved_max ; + + ------------------------------------------------------------ + function resolved_max ( s : bit_vector ) return bit is + ------------------------------------------------------------ + begin + return maximum(s) ; + end function resolved_max ; + + ------------------------------------------------------------ + function resolved_max ( s : integer_vector ) return integer is + ------------------------------------------------------------ + begin + return maximum(s) ; + end function resolved_max ; + + ------------------------------------------------------------ + function resolved_max ( s : time_vector ) return time is + ------------------------------------------------------------ + begin + return maximum(s) ; + end function resolved_max ; + + ------------------------------------------------------------ + function resolved_max ( s : real_vector ) return real is + ------------------------------------------------------------ + begin + return maximum(s) ; + end function resolved_max ; + + ------------------------------------------------------------ + function resolved_max ( s : string ) return character is + ------------------------------------------------------------ + begin + return maximum(s) ; + end function resolved_max ; + + ------------------------------------------------------------ + function resolved_max ( s : boolean_vector) return boolean is + ------------------------------------------------------------ + begin + return maximum(s) ; + end function resolved_max ; + + + -- resolved_sum - appropriate for numeric types + -- return sum of values that /= type'left + -- No initializations required on ports, default of type'left is ok + ------------------------------------------------------------ + function resolved_sum ( s : integer_vector ) return integer is + ------------------------------------------------------------ + variable result : integer := 0 ; + begin + for i in s'RANGE loop + if s(i) /= integer'left then + result := s(i) + result; + end if ; + end loop ; + return result ; + end function resolved_sum ; + + ------------------------------------------------------------ + function resolved_sum ( s : time_vector ) return time is + ------------------------------------------------------------ + variable result : time := 0 sec ; + begin + for i in s'RANGE loop + if s(i) /= time'left then + result := s(i) + result; + end if ; + end loop ; + return result ; + end function resolved_sum ; + + ------------------------------------------------------------ + function resolved_sum ( s : real_vector ) return real is + ------------------------------------------------------------ + variable result : real := 0.0 ; + begin + for i in s'RANGE loop + if s(i) /= real'left then + result := s(i) + result; + end if ; + end loop ; + return result ; + end function resolved_sum ; + + + -- resolved_weak + -- Special just for std_ulogic + -- No initializations required on ports, default of type'left is ok + type stdlogic_table is array(STD_ULOGIC, STD_ULOGIC) of STD_ULOGIC; + + constant weak_resolution_table : stdlogic_table := ( + -- Resolution order: Z < U < W < X < - < L < H < 0 < 1 + -- --------------------------------------------------------- + -- | U X 0 1 Z W L H - | | + -- --------------------------------------------------------- + ('U', 'X', '0', '1', 'U', 'W', 'L', 'H', '-'), -- | U | + ('X', 'X', '0', '1', 'X', 'X', 'L', 'H', '-'), -- | X | + ('0', '0', '0', '1', '0', '0', '0', '0', '0'), -- | 0 | + ('1', '1', '1', '1', '1', '1', '1', '1', '1'), -- | 1 | + ('U', 'X', '0', '1', 'Z', 'W', 'L', 'H', '-'), -- | Z | + ('W', 'X', '0', '1', 'W', 'W', 'L', 'H', '-'), -- | W | + ('L', 'L', '0', '1', 'L', 'L', 'L', 'H', 'L'), -- | L | + ('H', 'H', '0', '1', 'H', 'H', 'W', 'H', 'H'), -- | H | + ('-', '-', '0', '1', '-', '-', 'L', 'H', '-') -- | - | + ); + + ------------------------------------------------------------ + function resolved_weak (s : std_ulogic_vector) return std_ulogic is + ------------------------------------------------------------ + variable result : std_ulogic := 'Z' ; + begin + for i in s'RANGE loop + result := weak_resolution_table(result, s(i)) ; + end loop ; + return result ; + end function resolved_weak ; + + + -- legacy stuff. + -- requires ports to be initialized to 0 in the appropriate type. + + ------------------------------------------------------------ + function resolved ( s : integer_vector ) return integer is + -- requires interface to be initialized to 0 + ------------------------------------------------------------ + variable result : integer := 0 ; + variable failed : boolean := FALSE ; + begin + for i in s'RANGE loop + if s(i) /= 0 then + failed := failed or (result /= 0) ; + result := maximum(s(i),result); + end if ; + end loop ; + assert not failed report "ResolutionPkg.resolved: multiple drivers on integer" severity MULTIPLE_DRIVER_SEVERITY ; + -- AlertIf(OSVVM_ALERTLOG_ID, failed, "ResolutionPkg.resolved: multiple drivers on integer") ; + return result ; + end function resolved ; + + ------------------------------------------------------------ + function resolved ( s : time_vector ) return time is + -- requires interface to be initialized to 0 ns + ------------------------------------------------------------ + variable result : time := 0 ns ; + variable failed : boolean := FALSE ; + begin + for i in s'RANGE loop + if s(i) > 0 ns then + failed := failed or (result /= 0 ns) ; + result := maximum(s(i),result); + end if ; + end loop ; + assert not failed report "ResolutionPkg.resolved: multiple drivers on time" severity MULTIPLE_DRIVER_SEVERITY ; + -- AlertIf(OSVVM_ALERTLOG_ID, failed, "ResolutionPkg.resolved: multiple drivers on time") ; + return result ; + end function resolved ; + + ------------------------------------------------------------ + function resolved ( s : real_vector ) return real is + -- requires interface to be initialized to 0.0 + ------------------------------------------------------------ + variable result : real := 0.0 ; + variable failed : boolean := FALSE ; + begin + for i in s'RANGE loop + if s(i) /= 0.0 then + failed := failed or (result /= 0.0) ; + result := maximum(s(i),result); + end if ; + end loop ; + assert not failed report "ResolutionPkg.resolved: multiple drivers on real" severity MULTIPLE_DRIVER_SEVERITY ; + -- AlertIf(OSVVM_ALERTLOG_ID, failed, "ResolutionPkg.resolved: multiple drivers on real") ; + return result ; + end function resolved ; + + ------------------------------------------------------------ + function resolved (s : string) return character is + -- same as resolved_max + ------------------------------------------------------------ + variable result : character := NUL ; + variable failed : boolean := FALSE ; + begin + for i in s'RANGE loop + if s(i) /= NUL then + failed := failed or (result /= NUL) ; + result := maximum(result, s(i)) ; + end if ; + end loop ; + assert not failed report "ResolutionPkg.resolved: multiple drivers on character" severity MULTIPLE_DRIVER_SEVERITY ; + -- AlertIf(OSVVM_ALERTLOG_ID, failed, "ResolutionPkg.resolved: multiple drivers on character") ; + return result ; + end function resolved ; + + ------------------------------------------------------------ + function resolved ( s : boolean_vector) return boolean is + -- same as resolved_max + ------------------------------------------------------------ + variable result : boolean := FALSE ; + variable failed : boolean := FALSE ; + begin + for i in s'RANGE loop + if s(i) then + failed := failed or result ; + result := TRUE ; + end if ; + end loop ; + assert not failed report "ResolutionPkg.resolved: multiple drivers on boolean" severity MULTIPLE_DRIVER_SEVERITY ; + -- AlertIf(OSVVM_ALERTLOG_ID, failed, "ResolutionPkg.resolved: multiple drivers on boolean") ; + return result ; + end function resolved ; + +end package body ResolutionPkg ; diff --git a/OSVVM/ScoreboardGenericPkg.vhd b/OSVVM/ScoreboardGenericPkg.vhd new file mode 100644 index 0000000..ed43425 --- /dev/null +++ b/OSVVM/ScoreboardGenericPkg.vhd @@ -0,0 +1,1575 @@ +-- +-- File Name: ScoreBoardGenericPkg.vhd +-- Design Unit Name: ScoreBoardGenericPkg +-- Revision: STANDARD VERSION +-- +-- Maintainer: Jim Lewis email: jim@synthworks.com +-- Contributor(s): +-- Jim Lewis email: jim@synthworks.com +-- +-- +-- Description: +-- Defines types and methods to implement a FIFO based Scoreboard +-- Defines type ScoreBoardPType +-- Defines methods for putting values the scoreboard +-- +-- Developed for: +-- SynthWorks Design Inc. +-- VHDL Training Classes +-- 11898 SW 128th Ave. Tigard, Or 97223 +-- http://www.SynthWorks.com +-- +-- Latest standard version available at: +-- http://www.SynthWorks.com/downloads +-- +-- Revision History: +-- Date Version Description +-- 12/2006: 2006.12 Initial revision +-- 08/2010 2010.08 Added Tailpointer +-- 05/2012 2012.05 Changed FIFO to store pointers to ExpectedType +-- Allows usage of unconstrained arrays +-- 08/2012 2012.08 Added Type and Subprogram Generics +-- 08/2013 2013.08 Generics: to_string replaced write, Match replaced check +-- Added Tags - Experimental +-- Added Array of Scoreboards +-- 09/2013 2013.09 Added file handling, Check Count, Finish Status +-- Find, Flush +-- 06/2015 2015.06 Added Alerts, SetAlertLogID, Revised LocalPush, GetDropCount, +-- Deprecated SetFinish and ReportMode - REPORT_NONE, FileOpen +-- Deallocate, Initialized, Function SetName +-- 11/2016 2016.11 Released as part of OSVVM +-- 05/2017 2017.05 First print Actual then only print Expected if mis-match +-- +-- +-- Copyright (c) 2006 - 2016 by SynthWorks Design Inc. All rights reserved. +-- +-- Verbatim copies of this source file may be used and +-- distributed without restriction. +-- +-- This source file is free software; you can redistribute it +-- and/or modify it under the terms of the ARTISTIC License +-- as published by The Perl Foundation; either version 2.0 of +-- the License, or (at your option) any later version. +-- +-- This source is distributed in the hope that it will be +-- useful, but WITHOUT ANY WARRANTY; without even the implied +-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +-- PURPOSE. See the Artistic License for details. +-- +-- You should have received a copy of the license with this source. +-- If not download it from, +-- http://www.perlfoundation.org/artistic_license_2_0 +-- +-- + +use std.textio.all ; + +library ieee ; + use ieee.std_logic_1164.all ; + use ieee.numeric_std.all ; + + use work.TranscriptPkg.all ; + use work.AlertLogPkg.all ; + use work.NamePkg.all ; + + +package ScoreboardGenericPkg is + generic ( + type ExpectedType ; + type ActualType ; + function Match(Actual : ActualType ; -- defaults + Expected : ExpectedType) return boolean ; -- is "=" ; + function expected_to_string(A : ExpectedType) return string ; -- is to_string ; + function actual_to_string (A : ActualType) return string -- is to_string ; + ) ; + +-- -- For a VHDL-2002 package, comment out the generics and +-- -- uncomment the following, it replaces a generic instance of the package. +-- -- As a result, you will have multiple copies of the entire package. +-- -- Inconvenient, but ok as it still works the same. +-- subtype ExpectedType is std_logic_vector ; +-- subtype ActualType is std_logic_vector ; +-- alias Match is std_match [ActualType, ExpectedType return boolean] ; -- for std_logic_vector +-- alias expected_to_string is to_hstring [ExpectedType return string]; -- VHDL-2008 +-- alias actual_to_string is to_hstring [ActualType return string]; -- VHDL-2008 + + -- ScoreboardReportType is deprecated + -- Replaced by Affirmations. ERROR is the default. ALL turns on PASSED flag + type ScoreboardReportType is (REPORT_ERROR, REPORT_ALL, REPORT_NONE) ; -- replaced by affirmations + + type ScoreBoardPType is protected + + ------------------------------------------------------------ + -- Emulate arrays of scoreboards + procedure SetArrayIndex(L, R : integer) ; -- supports integer indices + procedure SetArrayIndex(R : natural) ; -- indicies 1 to R + impure function GetArrayIndex return integer_vector ; + impure function GetArrayLength return natural ; + + ------------------------------------------------------------ + -- Push items into the scoreboard/FIFO + + -- Simple Scoreboard, no tag + procedure Push (Item : in ExpectedType) ; + + -- Simple Tagged Scoreboard + procedure Push ( + constant Tag : in string ; + constant Item : in ExpectedType + ) ; + + -- Array of Scoreboards, no tag + procedure Push ( + constant Index : in integer ; + constant Item : in ExpectedType + ) ; + + -- Array of Tagged Scoreboards + procedure Push ( + constant Index : in integer ; + constant Tag : in string ; + constant Item : in ExpectedType + ) ; + +-- ------------------------------------------------------------ +-- -- Push items into the scoreboard/FIFO +-- -- Function form supports chaining of operations +-- -- In 2013, this caused overloading issues in some simulators, will retest later +-- +-- -- Simple Scoreboard, no tag +-- impure function Push (Item : ExpectedType) return ExpectedType ; +-- +-- -- Simple Tagged Scoreboard +-- impure function Push ( +-- constant Tag : in string ; +-- constant Item : in ExpectedType +-- ) return ExpectedType ; +-- +-- -- Array of Scoreboards, no tag +-- impure function Push ( +-- constant Index : in integer ; +-- constant Item : in ExpectedType +-- ) return ExpectedType ; +-- +-- -- Array of Tagged Scoreboards +-- impure function Push ( +-- constant Index : in integer ; +-- constant Tag : in string ; +-- constant Item : in ExpectedType +-- ) return ExpectedType ; -- for chaining of operations + + ------------------------------------------------------------ + -- Check received item with item in the scoreboard/FIFO + + -- Simple Scoreboard, no tag + procedure Check (ActualData : ActualType) ; + + -- Simple Tagged Scoreboard + procedure Check ( + constant Tag : in string ; + constant ActualData : in ActualType + ) ; + + -- Array of Scoreboards, no tag + procedure Check ( + constant Index : in integer ; + constant ActualData : in ActualType + ) ; + + -- Array of Tagged Scoreboards + procedure Check ( + constant Index : in integer ; + constant Tag : in string ; + constant ActualData : in ActualType + ) ; + + ------------------------------------------------------------ + -- Pop the top item (FIFO) from the scoreboard/FIFO + + -- Simple Scoreboard, no tag + procedure Pop (variable Item : out ExpectedType) ; + + -- Simple Tagged Scoreboard + procedure Pop ( + constant Tag : in string ; + variable Item : out ExpectedType + ) ; + + -- Array of Scoreboards, no tag + procedure Pop ( + constant Index : in integer ; + variable Item : out ExpectedType + ) ; + + -- Array of Tagged Scoreboards + procedure Pop ( + constant Index : in integer ; + constant Tag : in string ; + variable Item : out ExpectedType + ) ; + +-- ------------------------------------------------------------ +-- -- Pop the top item (FIFO) from the scoreboard/FIFO +-- -- Function form supports chaining of operations +-- -- In 2013, this caused overloading issues in some simulators, will retest later +-- +-- -- Simple Scoreboard, no tag +-- impure function Pop return ExpectedType ; +-- +-- -- Simple Tagged Scoreboard +-- impure function Pop ( +-- constant Tag : in string +-- ) return ExpectedType ; +-- +-- -- Array of Scoreboards, no tag +-- impure function Pop (Index : integer) return ExpectedType ; +-- +-- -- Array of Tagged Scoreboards +-- impure function Pop ( +-- constant Index : in integer ; +-- constant Tag : in string +-- ) return ExpectedType ; + + ------------------------------------------------------------ + -- Empty - check to see if scoreboard is empty + impure function Empty return boolean ; -- Simple + impure function Empty (Tag : String) return boolean ; -- Simple, Tagged + impure function Empty (Index : integer) return boolean ; -- Array + impure function Empty (Index : integer; Tag : String) return boolean ; -- Array, Tagged + + ------------------------------------------------------------ + -- SetAlertLogID - associate an AlertLogID with a scoreboard to allow integrated error reporting + procedure SetAlertLogID(Index : Integer ; Name : string ; ParentID : AlertLogIDType := ALERTLOG_BASE_ID ; CreateHierarchy : Boolean := TRUE) ; + procedure SetAlertLogID(Name : string ; ParentID : AlertLogIDType := ALERTLOG_BASE_ID ; CreateHierarchy : Boolean := TRUE) ; + -- Use when an AlertLogID is used by multiple items (Model or other Scoreboards). See also AlertLogPkg.GetAlertLogID + procedure SetAlertLogID (Index : Integer ; A : AlertLogIDType) ; + procedure SetAlertLogID (A : AlertLogIDType) ; + impure function GetAlertLogID(Index : Integer) return AlertLogIDType ; + impure function GetAlertLogID return AlertLogIDType ; + + ------------------------------------------------------------ + -- Set a scoreboard name. + -- Used when scoreboard AlertLogID is shared between different sources. + procedure SetName (Name : String) ; + impure function SetName (Name : String) return string ; + impure function GetName (DefaultName : string := "Scoreboard") return string ; + + + ------------------------------------------------------------ + -- Scoreboard Introspection + + -- Number of items put into scoreboard + impure function GetItemCount return integer ; -- Simple, with or without tags + impure function GetItemCount (Index : integer) return integer ; -- Arrays, with or without tags + + -- Number of items checked by scoreboard + impure function GetCheckCount return integer ; -- Simple, with or without tags + impure function GetCheckCount (Index : integer) return integer ; -- Arrays, with or without tags + + -- Number of items dropped by scoreboard. See Find/Flush + impure function GetDropCount return integer ; -- Simple, with or without tags + impure function GetDropCount (Index : integer) return integer ; -- Arrays, with or without tags + + ------------------------------------------------------------ + -- Find - Returns the ItemNumber for a value and tag (if applicable) in a scoreboard. + -- Find returns integer'left if no match found + -- Also See Flush. Flush will drop items up through the ItemNumber + + -- Simple Scoreboard + impure function Find ( + constant ActualData : in ActualType + ) return integer ; + + -- Tagged Scoreboard + impure function Find ( + constant Tag : in string; + constant ActualData : in ActualType + ) return integer ; + + -- Array of Simple Scoreboards + impure function Find ( + constant Index : in integer ; + constant ActualData : in ActualType + ) return integer ; + + -- Array of Tagged Scoreboards + impure function Find ( + constant Index : in integer ; + constant Tag : in string; + constant ActualData : in ActualType + ) return integer ; + + ------------------------------------------------------------ + -- Flush - Remove elements in the scoreboard upto and including the one with ItemNumber + -- See Find to identify an ItemNumber of a particular value and tag (if applicable) + + -- Simple Scoreboard + procedure Flush ( + constant ItemNumber : in integer + ) ; + + -- Tagged Scoreboard - only removes items that also match the tag + procedure Flush ( + constant Tag : in string ; + constant ItemNumber : in integer + ) ; + + -- Array of Simple Scoreboards + procedure Flush ( + constant Index : in integer ; + constant ItemNumber : in integer + ) ; + + -- Array of Tagged Scoreboards - only removes items that also match the tag + procedure Flush ( + constant Index : in integer ; + constant Tag : in string ; + constant ItemNumber : in integer + ) ; + + ------------------------------------------------------------ + -- Generally these are not required. When a simulation ends and + -- another simulation is started, a simulator will release all allocated items. + procedure Deallocate ; -- Deletes all allocated items + procedure Initialize ; -- Creates initial data structure if it was destroyed with Deallocate + + + ------------------------------------------------------------ + ------------------------------------------------------------ + -- Deprecated. Use alerts directly instead. + -- AlertIF(SB.GetCheckCount < 10, ....) ; + -- AlertIf(Not SB.Empty, ...) ; + ------------------------------------------------------------ + -- Set alerts if scoreboard not empty or if CheckCount < + -- Use if need to check empty or CheckCount for a specific scoreboard. + + -- Simple Scoreboards, with or without tag + procedure CheckFinish ( + FinishCheckCount : integer ; + FinishEmpty : boolean + ) ; + + -- Array of Scoreboards, with or without tag + procedure CheckFinish ( + Index : integer ; + FinishCheckCount : integer ; + FinishEmpty : boolean + ) ; + + ------------------------------------------------------------ + -- Get error count + -- Deprecated, replaced by usage of Alerts + -- AlertFLow: Instead use AlertLogPkg.ReportAlerts or AlertLogPkg.GetAlertCount + -- Not AlertFlow: use GetErrorCount to get total error count + + -- Simple Scoreboards, with or without tag + impure function GetErrorCount return integer ; + + -- Array of Scoreboards, with or without tag + impure function GetErrorCount(Index : integer) return integer ; + + ------------------------------------------------------------ + -- Error count manipulation + + -- IncErrorCount - not recommended, use alerts instead - may be deprecated in the future + procedure IncErrorCount ; -- Simple, with or without tags + procedure IncErrorCount (Index : integer) ; -- Arrays, with or without tags + + -- Clear error counter. Caution does not change AlertCounts, must also use AlertLogPkg.ClearAlerts + procedure SetErrorCountZero ; -- Simple, with or without tags + procedure SetErrorCountZero (Index : integer) ; -- Arrays, with or without tags + + ------------------------------------------------------------ + ------------------------------------------------------------ + -- Deprecated. Names changed. Maintained for backward compatibility - would prefer an alias + ------------------------------------------------------------ + procedure FileOpen (FileName : string; OpenKind : File_Open_Kind ) ; -- Replaced by TranscriptPkg.TranscriptOpen + procedure PutExpectedData (ExpectedData : ExpectedType) ; -- Replaced by push + procedure CheckActualData (ActualData : ActualType) ; -- Replaced by Check + impure function GetItemNumber return integer ; -- Replaced by GetItemCount + procedure SetMessage (MessageIn : String) ; -- Replaced by SetName + impure function GetMessage return string ; -- Replaced by GetName + + -- Deprecated and may be deleted in a future revision + procedure SetFinish ( -- Replaced by CheckFinish + Index : integer ; + FCheckCount : integer ; + FEmpty : boolean := TRUE; + FStatus : boolean := TRUE + ) ; + + procedure SetFinish ( -- Replaced by CheckFinish + FCheckCount : integer ; + FEmpty : boolean := TRUE; + FStatus : boolean := TRUE + ) ; + + ------------------------------------------------------------ + -- SetReportMode + -- Not AlertFlow + -- REPORT_ALL: Replaced by AlertLogPkg.SetLogEnable(PASSED, TRUE) + -- REPORT_ERROR: Replaced by AlertLogPkg.SetLogEnable(PASSED, FALSE) + -- REPORT_NONE: Deprecated, do not use. + -- AlertFlow: + -- REPORT_ALL: Replaced by AlertLogPkg.SetLogEnable(AlertLogID, PASSED, TRUE) + -- REPORT_ERROR: Replaced by AlertLogPkg.SetLogEnable(AlertLogID, PASSED, FALSE) + -- REPORT_NONE: Replaced by AlertLogPkg.SetAlertEnable(AlertLogID, ERROR, FALSE) + procedure SetReportMode (ReportModeIn : ScoreboardReportType) ; + impure function GetReportMode return ScoreboardReportType ; + + + end protected ScoreBoardPType ; + +end ScoreboardGenericPkg ; + + +-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +package body ScoreboardGenericPkg is + + type ScoreBoardPType is protected body + type ExpectedPointerType is access ExpectedType ; + + type ListType ; + type ListPointerType is access ListType ; + type ListType is record + ItemNumber : integer ; + TagPtr : line ; + ExpectedPtr : ExpectedPointerType ; + NextPtr : ListPointerType ; + end record ; + type ListArrayType is array (integer range <>) of ListPointerType ; + type ListArrayPointerType is access ListArrayType ; + + variable ArrayLengthVar : integer := 1 ; + variable HeadPointer : ListArrayPointerType := new ListArrayType(1 to 1) ; + variable TailPointer : ListArrayPointerType := new ListArrayType(1 to 1) ; + variable PopListPointer : ListArrayPointerType := new ListArrayType(1 to 1) ; + + type IntegerArrayType is array (integer range <>) of Integer ; + type IntegerArrayPointerType is access IntegerArrayType ; + + variable ErrCntVar : IntegerArrayPointerType := new IntegerArrayType'(1 => 0) ; + variable DropCountVar : IntegerArrayPointerType := new IntegerArrayType'(1 => 0) ; + variable ItemNumberVar : IntegerArrayPointerType := new IntegerArrayType'(1 => 0) ; + variable CheckCountVar : IntegerArrayPointerType := new IntegerArrayType'(1 => 0) ; + variable AlertLogIDVar : IntegerArrayPointerType := new IntegerArrayType'(1 => OSVVM_SCOREBOARD_ALERTLOG_ID) ; + + variable NameVar : NamePType ; + variable ReportModeVar : ScoreboardReportType ; + variable FirstIndexVar : integer := 1 ; + + + ------------------------------------------------------------ + procedure SetName (Name : String) is + ------------------------------------------------------------ + begin + NameVar.Set(Name) ; + end procedure SetName ; + + ------------------------------------------------------------ + impure function SetName (Name : String) return string is + ------------------------------------------------------------ + begin + NameVar.Set(Name) ; + return Name ; + end function SetName ; + + ------------------------------------------------------------ + impure function GetName (DefaultName : string := "Scoreboard") return string is + ------------------------------------------------------------ + begin + return NameVar.Get(DefaultName) ; + end function GetName ; + + ------------------------------------------------------------ + procedure SetReportMode (ReportModeIn : ScoreboardReportType) is + ------------------------------------------------------------ + begin + ReportModeVar := ReportModeIn ; + if ReportModeVar = REPORT_ALL then + Alert(OSVVM_SCOREBOARD_ALERTLOG_ID, "ScoreboardGenericPkg.SetReportMode: To turn off REPORT_ALL, use osvvm.AlertLogPkg.SetLogEnable(PASSED, FALSE)", WARNING) ; + for i in AlertLogIDVar'range loop + SetLogEnable(AlertLogIDVar(i), PASSED, TRUE) ; + end loop ; + end if ; + if ReportModeVar = REPORT_NONE then + Alert(OSVVM_SCOREBOARD_ALERTLOG_ID, "ScoreboardGenericPkg.SetReportMode: ReportMode REPORT_NONE has been deprecated and will be removed in next revision. Please contact OSVVM architect Jim Lewis if you need this capability.", WARNING) ; + end if ; + end procedure SetReportMode ; + + ------------------------------------------------------------ + impure function GetReportMode return ScoreboardReportType is + ------------------------------------------------------------ + begin + return ReportModeVar ; + end function GetReportMode ; + + ------------------------------------------------------------ + procedure SetArrayIndex(L, R : integer) is + ------------------------------------------------------------ + variable OldHeadPointer, OldTailPointer, OldPopListPointer : ListArrayPointerType ; + variable OldErrCnt, OldDropCount, OldItemNumber, OldCheckCount, OldAlertLogIDVar : IntegerArrayPointerType ; + variable Min, Max, Len, OldLen, OldMax : integer ; + begin + Min := minimum(L, R) ; + Max := maximum(L, R) ; + OldLen := ArrayLengthVar ; + OldMax := Min + ArrayLengthVar - 1 ; + Len := Max - Min + 1 ; + ArrayLengthVar := Len ; + if Len >= OldLen then + FirstIndexVar := Min ; + + OldHeadPointer := HeadPointer ; + HeadPointer := new ListArrayType(Min to Max) ; + if OldHeadPointer /= NULL then + HeadPointer(Min to OldMax) := OldHeadPointer.all ; -- (OldHeadPointer'range) ; + Deallocate(OldHeadPointer) ; + end if ; + + OldTailPointer := TailPointer ; + TailPointer := new ListArrayType(Min to Max) ; + if OldTailPointer /= NULL then + TailPointer(Min to OldMax) := OldTailPointer.all ; + Deallocate(OldTailPointer) ; + end if ; + + OldPopListPointer := PopListPointer ; + PopListPointer := new ListArrayType(Min to Max) ; + if OldPopListPointer /= NULL then + PopListPointer(Min to OldMax) := OldPopListPointer.all ; + Deallocate(OldPopListPointer) ; + end if ; + + OldErrCnt := ErrCntVar ; + ErrCntVar := new IntegerArrayType'(Min to Max => 0) ; + if OldErrCnt /= NULL then + ErrCntVar(Min to OldMax) := OldErrCnt.all ; + Deallocate(OldErrCnt) ; + end if ; + + OldDropCount := DropCountVar ; + DropCountVar := new IntegerArrayType'(Min to Max => 0) ; + if OldDropCount /= NULL then + DropCountVar(Min to OldMax) := OldDropCount.all ; + Deallocate(OldDropCount) ; + end if ; + + OldItemNumber := ItemNumberVar ; + ItemNumberVar := new IntegerArrayType'(Min to Max => 0) ; + if OldItemNumber /= NULL then + ItemNumberVar(Min to OldMax) := OldItemNumber.all ; + Deallocate(OldItemNumber) ; + end if ; + + OldCheckCount := CheckCountVar ; + CheckCountVar := new IntegerArrayType'(Min to Max => 0) ; + if OldCheckCount /= NULL then + CheckCountVar(Min to OldMax) := OldCheckCount.all ; + Deallocate(OldCheckCount) ; + end if ; + + OldAlertLogIDVar := AlertLogIDVar ; + AlertLogIDVar := new IntegerArrayType'(Min to Max => OSVVM_SCOREBOARD_ALERTLOG_ID) ; + if OldAlertLogIDVar /= NULL then + AlertLogIDVar(Min to OldMax) := OldAlertLogIDVar.all ; + Deallocate(OldAlertLogIDVar) ; + end if ; + + elsif Len < OldLen then + report "ScoreboardGenericPkg: SetArrayIndex, new array Length <= current array length" + severity failure ; + + end if ; + end procedure SetArrayIndex ; + + ------------------------------------------------------------ + procedure SetArrayIndex(R : natural) is + ------------------------------------------------------------ + begin + SetArrayIndex(1, R) ; + end procedure SetArrayIndex ; + + ------------------------------------------------------------ + procedure Deallocate is + ------------------------------------------------------------ + variable CurListPtr, LastListPtr : ListPointerType ; + begin + for Index in HeadPointer'range loop + -- Deallocate contents in the scoreboards + CurListPtr := HeadPointer(Index) ; + while CurListPtr /= Null loop + deallocate(CurListPtr.TagPtr) ; + deallocate(CurListPtr.ExpectedPtr) ; + LastListPtr := CurListPtr ; + CurListPtr := CurListPtr.NextPtr ; + Deallocate(LastListPtr) ; + end loop ; + end loop ; + + for Index in PopListPointer'range loop + -- Deallocate PopListPointer - only has single element + CurListPtr := PopListPointer(Index) ; + if CurListPtr /= NULL then + deallocate(CurListPtr.TagPtr) ; + deallocate(CurListPtr.ExpectedPtr) ; + deallocate(CurListPtr) ; + end if ; + end loop ; + + -- Deallocate arrays of pointers + Deallocate(HeadPointer) ; + Deallocate(TailPointer) ; + Deallocate(PopListPointer) ; + + -- Deallocate supporting arrays + Deallocate(ErrCntVar) ; + Deallocate(DropCountVar) ; + Deallocate(ItemNumberVar) ; + Deallocate(CheckCountVar) ; + Deallocate(AlertLogIDVar) ; + + -- Deallocate NameVar - NamePType + NameVar.Deallocate ; + + ArrayLengthVar := 0 ; + end procedure Deallocate ; + + ------------------------------------------------------------ + -- Construct initial data structure + procedure Initialize is + ------------------------------------------------------------ + begin + SetArrayIndex(1, 1) ; + end procedure Initialize ; + + ------------------------------------------------------------ + impure function GetArrayIndex return integer_vector is + ------------------------------------------------------------ + begin + return (1 => HeadPointer'left, 2 => HeadPointer'right) ; + end function GetArrayIndex ; + + ------------------------------------------------------------ + impure function GetArrayLength return natural is + ------------------------------------------------------------ + begin + return ArrayLengthVar ; -- HeadPointer'length ; + end function GetArrayLength ; + + ------------------------------------------------------------ + procedure SetAlertLogID (Index : Integer ; A : AlertLogIDType) is + ------------------------------------------------------------ + begin + AlertLogIDVar(Index) := A ; + end procedure SetAlertLogID ; + + ------------------------------------------------------------ + procedure SetAlertLogID (A : AlertLogIDType) is + ------------------------------------------------------------ + begin + AlertLogIDVar(FirstIndexVar) := A ; + end procedure SetAlertLogID ; + + ------------------------------------------------------------ + procedure SetAlertLogID(Index : Integer ; Name : string ; ParentID : AlertLogIDType := ALERTLOG_BASE_ID ; CreateHierarchy : Boolean := TRUE) is + ------------------------------------------------------------ + begin + AlertLogIDVar(Index) := GetAlertLogID(Name, ParentID, CreateHierarchy) ; + end procedure SetAlertLogID ; + + ------------------------------------------------------------ + procedure SetAlertLogID(Name : string ; ParentID : AlertLogIDType := ALERTLOG_BASE_ID ; CreateHierarchy : Boolean := TRUE) is + ------------------------------------------------------------ + begin + AlertLogIDVar(FirstIndexVar) := GetAlertLogID(Name, ParentID, CreateHierarchy) ; + end procedure SetAlertLogID ; + + ------------------------------------------------------------ + impure function GetAlertLogID(Index : Integer) return AlertLogIDType is + ------------------------------------------------------------ + begin + return AlertLogIDVar(Index) ; + end function GetAlertLogID ; + + ------------------------------------------------------------ + impure function GetAlertLogID return AlertLogIDType is + ------------------------------------------------------------ + begin + return AlertLogIDVar(FirstIndexVar) ; + end function GetAlertLogID ; + + ------------------------------------------------------------ + impure function LocalOutOfRange( + ------------------------------------------------------------ + constant Index : in integer ; + constant Name : in string + ) return boolean is + begin + return AlertIf(OSVVM_SCOREBOARD_ALERTLOG_ID, Index < HeadPointer'Low or Index > HeadPointer'High, + GetName & " " & Name & " Index: " & to_string(Index) & + "is not in the range (" & to_string(HeadPointer'Low) & + "to " & to_string(HeadPointer'High) & ")", + FAILURE ) ; + end function LocalOutOfRange ; + + ------------------------------------------------------------ + procedure LocalPush ( + ------------------------------------------------------------ + constant Index : in integer ; + constant Tag : in string ; + constant Item : in ExpectedType + ) is + variable ExpectedPtr : ExpectedPointerType ; + variable TagPtr : line ; + begin + if LocalOutOfRange(Index, "Push") then + return ; -- error reporting in LocalOutOfRange + end if ; + + ItemNumberVar(Index) := ItemNumberVar(Index) + 1 ; + ExpectedPtr := new ExpectedType'(Item) ; + TagPtr := new string'(Tag) ; + + if HeadPointer(Index) = NULL then + -- 2015.05: allocation using ListTtype'(...) in a protected type does not work in some simulators + -- HeadPointer(Index) := new ListType'(ItemNumberVar(Index), TagPtr, ExpectedPtr, NULL) ; + HeadPointer(Index) := new ListType ; + HeadPointer(Index).ItemNumber := ItemNumberVar(Index) ; + HeadPointer(Index).TagPtr := TagPtr ; + HeadPointer(Index).ExpectedPtr := ExpectedPtr ; + HeadPointer(Index).NextPtr := NULL ; + TailPointer(Index) := HeadPointer(Index) ; + else + -- 2015.05: allocation using ListTtype'(...) in a protected type does not work in some simulators + -- TailPointer(Index).NextPtr := new ListType'(ItemNumberVar(Index), TagPtr, ExpectedPtr, NULL) ; + TailPointer(Index).NextPtr := new ListType ; + TailPointer(Index).NextPtr.ItemNumber := ItemNumberVar(Index) ; + TailPointer(Index).NextPtr.TagPtr := TagPtr ; + TailPointer(Index).NextPtr.ExpectedPtr := ExpectedPtr ; + TailPointer(Index).NextPtr.NextPtr := NULL ; + TailPointer(Index) := TailPointer(Index).NextPtr ; + end if ; + end procedure LocalPush ; + + ------------------------------------------------------------ + -- Array of Tagged Scoreboards + procedure Push ( + ------------------------------------------------------------ + constant Index : in integer ; + constant Tag : in string ; + constant Item : in ExpectedType + ) is + variable ExpectedPtr : ExpectedPointerType ; + variable TagPtr : line ; + begin + if LocalOutOfRange(Index, "Push") then + return ; -- error reporting in LocalOutOfRange + end if ; + LocalPush(Index, Tag, Item) ; + end procedure Push ; + + ------------------------------------------------------------ + -- Array of Scoreboards, no tag + procedure Push ( + ------------------------------------------------------------ + constant Index : in integer ; + constant Item : in ExpectedType + ) is + begin + if LocalOutOfRange(Index, "Push") then + return ; -- error reporting in LocalOutOfRange + end if ; + LocalPush(Index, "", Item) ; + end procedure Push ; + + ------------------------------------------------------------ + -- Simple Tagged Scoreboard + procedure Push ( + ------------------------------------------------------------ + constant Tag : in string ; + constant Item : in ExpectedType + ) is + begin + LocalPush(FirstIndexVar, Tag, Item) ; + end procedure Push ; + + ------------------------------------------------------------ + -- Simple Scoreboard, no tag + procedure Push (Item : in ExpectedType) is + ------------------------------------------------------------ + begin + LocalPush(FirstIndexVar, "", Item) ; + end procedure Push ; + + ------------------------------------------------------------ + -- Array of Tagged Scoreboards + impure function Push ( + ------------------------------------------------------------ + constant Index : in integer ; + constant Tag : in string ; + constant Item : in ExpectedType + ) return ExpectedType is + begin + if LocalOutOfRange(Index, "Push") then + return Item ; -- error reporting in LocalOutOfRange + end if ; + LocalPush(Index, Tag, Item) ; + return Item ; + end function Push ; + + ------------------------------------------------------------ + -- Array of Scoreboards, no tag + impure function Push ( + ------------------------------------------------------------ + constant Index : in integer ; + constant Item : in ExpectedType + ) return ExpectedType is + begin + if LocalOutOfRange(Index, "Push") then + return Item ; -- error reporting in LocalOutOfRange + end if ; + LocalPush(Index, "", Item) ; + return Item ; + end function Push ; + + ------------------------------------------------------------ + -- Simple Tagged Scoreboard + impure function Push ( + ------------------------------------------------------------ + constant Tag : in string ; + constant Item : in ExpectedType + ) return ExpectedType is + begin + LocalPush(FirstIndexVar, Tag, Item) ; + return Item ; + end function Push ; + + ------------------------------------------------------------ + -- Simple Scoreboard, no tag + impure function Push (Item : ExpectedType) return ExpectedType is + ------------------------------------------------------------ + begin + LocalPush(FirstIndexVar, "", Item) ; + return Item ; + end function Push ; + + ------------------------------------------------------------ + -- Local Only + -- Pops highest element matching Tag into PopListPointer(Index) + procedure LocalPop (Index : integer ; Tag : string; Name : string) is + ------------------------------------------------------------ + variable CurPtr : ListPointerType ; + begin + if LocalOutOfRange(Index, "Pop/Check") then + return ; -- error reporting in LocalOutOfRange + end if ; + if HeadPointer(Index) = NULL then + ErrCntVar(Index) := ErrCntVar(Index) + 1 ; + Alert(AlertLogIDVar(Index), GetName & " Empty during " & Name, FAILURE) ; + return ; + end if ; + -- deallocate previous pointer + if PopListPointer(Index) /= NULL then + deallocate(PopListPointer(Index).TagPtr) ; + deallocate(PopListPointer(Index).ExpectedPtr) ; + deallocate(PopListPointer(Index)) ; + end if ; + -- Descend to find Tag field and extract + CurPtr := HeadPointer(Index) ; + if CurPtr.TagPtr.all = Tag then + -- Non-tagged scoreboards find this one. + PopListPointer(Index) := HeadPointer(Index) ; + HeadPointer(Index) := HeadPointer(Index).NextPtr ; + else + loop + if CurPtr.NextPtr = NULL then + ErrCntVar(Index) := ErrCntVar(Index) + 1 ; + Alert(AlertLogIDVar(Index), GetName & " Pop/Check (" & Name & "), tag: " & Tag & " not found", FAILURE) ; + exit ; + elsif CurPtr.NextPtr.TagPtr.all = Tag then + PopListPointer(Index) := CurPtr.NextPtr ; + CurPtr.NextPtr := CurPtr.NextPtr.NextPtr ; + if CurPtr.NextPtr = NULL then + TailPointer(Index) := CurPtr ; + end if ; + exit ; + else + CurPtr := CurPtr.NextPtr ; + end if ; + end loop ; + end if ; + end procedure LocalPop ; + + ------------------------------------------------------------ + -- Local Only + procedure LocalCheck ( + ------------------------------------------------------------ + constant Index : in integer ; + constant ActualData : in ActualType + ) is + variable ExpectedPtr : ExpectedPointerType ; + variable CurrentItem : integer ; + variable WriteBuf : line ; + variable FoundError : boolean ; + begin + CheckCountVar(Index) := CheckCountVar(Index) + 1 ; + ExpectedPtr := PopListPointer(Index).ExpectedPtr ; + CurrentItem := PopListPointer(Index).ItemNumber ; + + if not Match(ActualData, ExpectedPtr.all) then + ErrCntVar(Index) := ErrCntVar(Index) + 1 ; + FoundError := TRUE ; + else + FoundError := FALSE ; + end if ; + + IncAffirmCount ; + +-- if FoundError or ReportModeVar = REPORT_ALL then + if FoundError or GetLogEnable(AlertLogIDVar(Index), PASSED) then + if AlertLogIDVar(Index) = OSVVM_SCOREBOARD_ALERTLOG_ID then + write(WriteBuf, GetName(DefaultName => "Scoreboard")) ; + else + write(WriteBuf, GetName(DefaultName => "")) ; + end if ; + if ArrayLengthVar > 1 then + write(WriteBuf, " (" & to_string(Index) & ") ") ; + end if ; + write(WriteBuf, " Received: " & actual_to_string(ActualData)) ; + if FoundError then + write(WriteBuf, " Expected: " & expected_to_string(ExpectedPtr.all)) ; + end if ; + if PopListPointer(Index).TagPtr.all /= "" then + write(WriteBuf, " Tag: " & PopListPointer(Index).TagPtr.all) ; + end if; + write(WriteBuf, " Item Number: " & to_string(CurrentItem)) ; + if FoundError then + if ReportModeVar /= REPORT_NONE then + -- Affirmation Failed + Alert(AlertLogIDVar(Index), WriteBuf.all, ERROR) ; + else + -- Affirmation Failed, but silent, unless in DEBUG mode + Log(AlertLogIDVar(Index), "ERROR " & WriteBuf.all, DEBUG) ; + IncAlertCount(AlertLogIDVar(Index)) ; -- Silent Counted Alert + end if ; + else + -- Affirmation passed + Log(AlertLogIDVar(Index), WriteBuf.all, PASSED) ; + end if ; + deallocate(WriteBuf) ; + end if ; + end procedure LocalCheck ; + + ------------------------------------------------------------ + -- Array of Tagged Scoreboards + procedure Check ( + ------------------------------------------------------------ + constant Index : in integer ; + constant Tag : in string ; + constant ActualData : in ActualType + ) is + begin + if LocalOutOfRange(Index, "Check") then + return ; -- error reporting in LocalOutOfRange + end if ; + LocalPop(Index, Tag, "Check") ; + LocalCheck(Index, ActualData) ; + end procedure Check ; + + ------------------------------------------------------------ + -- Array of Scoreboards, no tag + procedure Check ( + ------------------------------------------------------------ + constant Index : in integer ; + constant ActualData : in ActualType + ) is + begin + if LocalOutOfRange(Index, "Check") then + return ; -- error reporting in LocalOutOfRange + end if ; + LocalPop(Index, "", "Check") ; + LocalCheck(Index, ActualData) ; + end procedure Check ; + + ------------------------------------------------------------ + -- Simple Tagged Scoreboard + procedure Check ( + ------------------------------------------------------------ + constant Tag : in string ; + constant ActualData : in ActualType + ) is + begin + LocalPop(FirstIndexVar, Tag, "Check") ; + LocalCheck(FirstIndexVar, ActualData) ; + end procedure Check ; + + ------------------------------------------------------------ + -- Simple Scoreboard, no tag + procedure Check (ActualData : ActualType) is + ------------------------------------------------------------ + begin + LocalPop(FirstIndexVar, "", "Check") ; + LocalCheck(FirstIndexVar, ActualData) ; + end procedure Check ; + + ------------------------------------------------------------ + -- Array of Tagged Scoreboards + procedure Pop ( + ------------------------------------------------------------ + constant Index : in integer ; + constant Tag : in string ; + variable Item : out ExpectedType + ) is + begin + if LocalOutOfRange(Index, "Pop") then + return ; -- error reporting in LocalOutOfRange + end if ; + LocalPop(Index, Tag, "Pop") ; + Item := PopListPointer(Index).ExpectedPtr.all ; + end procedure Pop ; + + ------------------------------------------------------------ + -- Array of Scoreboards, no tag + procedure Pop ( + ------------------------------------------------------------ + constant Index : in integer ; + variable Item : out ExpectedType + ) is + begin + if LocalOutOfRange(Index, "Pop") then + return ; -- error reporting in LocalOutOfRange + end if ; + LocalPop(Index, "", "Pop") ; + Item := PopListPointer(Index).ExpectedPtr.all ; + end procedure Pop ; + + ------------------------------------------------------------ + -- Simple Tagged Scoreboard + procedure Pop ( + ------------------------------------------------------------ + constant Tag : in string ; + variable Item : out ExpectedType + ) is + begin + LocalPop(FirstIndexVar, Tag, "Pop") ; + Item := PopListPointer(FirstIndexVar).ExpectedPtr.all ; + end procedure Pop ; + + ------------------------------------------------------------ + -- Simple Scoreboard, no tag + procedure Pop (variable Item : out ExpectedType) is + ------------------------------------------------------------ + begin + LocalPop(FirstIndexVar, "", "Pop") ; + Item := PopListPointer(FirstIndexVar).ExpectedPtr.all ; + end procedure Pop ; + + ------------------------------------------------------------ + -- Array of Tagged Scoreboards + impure function Pop ( + ------------------------------------------------------------ + constant Index : in integer ; + constant Tag : in string + ) return ExpectedType is + begin + if LocalOutOfRange(Index, "Pop") then + -- error reporting in LocalOutOfRange + return PopListPointer(FirstIndexVar).ExpectedPtr.all ; + end if ; + LocalPop(Index, Tag, "Pop") ; + return PopListPointer(Index).ExpectedPtr.all ; + end function Pop ; + + ------------------------------------------------------------ + -- Array of Scoreboards, no tag + impure function Pop (Index : integer) return ExpectedType is + ------------------------------------------------------------ + begin + if LocalOutOfRange(Index, "Pop") then + -- error reporting in LocalOutOfRange + return PopListPointer(FirstIndexVar).ExpectedPtr.all ; + end if ; + LocalPop(Index, "", "Pop") ; + return PopListPointer(Index).ExpectedPtr.all ; + end function Pop ; + + ------------------------------------------------------------ + -- Simple Tagged Scoreboard + impure function Pop ( + ------------------------------------------------------------ + constant Tag : in string + ) return ExpectedType is + begin + LocalPop(FirstIndexVar, Tag, "Pop") ; + return PopListPointer(FirstIndexVar).ExpectedPtr.all ; + end function Pop ; + + ------------------------------------------------------------ + -- Simple Scoreboard, no tag + impure function Pop return ExpectedType is + ------------------------------------------------------------ + begin + LocalPop(FirstIndexVar, "", "Pop") ; + return PopListPointer(FirstIndexVar).ExpectedPtr.all ; + end function Pop ; + + ------------------------------------------------------------ + -- Array of Tagged Scoreboards + impure function Empty (Index : integer; Tag : String) return boolean is + ------------------------------------------------------------ + variable CurPtr : ListPointerType ; + begin + CurPtr := HeadPointer(Index) ; + while CurPtr /= NULL loop + if CurPtr.TagPtr.all = Tag then + return FALSE ; -- Found Tag + end if ; + CurPtr := CurPtr.NextPtr ; + end loop ; + return TRUE ; -- Tag not found + end function Empty ; + + ------------------------------------------------------------ + -- Array of Scoreboards, no tag + impure function Empty (Index : integer) return boolean is + ------------------------------------------------------------ + begin + return HeadPointer(Index) = NULL ; + end function Empty ; + + ------------------------------------------------------------ + -- Simple Tagged Scoreboard + impure function Empty (Tag : String) return boolean is + ------------------------------------------------------------ + variable CurPtr : ListPointerType ; + begin + return Empty(FirstIndexVar, Tag) ; + end function Empty ; + + ------------------------------------------------------------ + -- Simple Scoreboard, no tag + impure function Empty return boolean is + ------------------------------------------------------------ + begin + return HeadPointer(FirstIndexVar) = NULL ; + end function Empty ; + + ------------------------------------------------------------ + procedure CheckFinish ( + ------------------------------------------------------------ + Index : integer ; + FinishCheckCount : integer ; + FinishEmpty : boolean + ) is + variable EmptyError : Boolean ; + variable WriteBuf : line ; + begin + if AlertLogIDVar(Index) = OSVVM_SCOREBOARD_ALERTLOG_ID then + write(WriteBuf, GetName(DefaultName => "Scoreboard")) ; + else + write(WriteBuf, GetName(DefaultName => "")) ; + end if ; + if ArrayLengthVar > 1 then + if WriteBuf.all /= "" then + swrite(WriteBuf, " ") ; + end if ; + write(WriteBuf, "Index(" & to_string(Index) & "), ") ; + else + if WriteBuf.all /= "" then + swrite(WriteBuf, ", ") ; + end if ; + end if ; + if FinishEmpty then + AffirmIf(AlertLogIDVar(Index), Empty(Index), WriteBuf.all & "Checking Empty: " & to_string(Empty(Index)) & + " FinishEmpty: " & to_string(FinishEmpty)) ; + if not Empty(Index) then + -- Increment internal count on FinishEmpty Error + ErrCntVar(Index) := ErrCntVar(Index) + 1 ; + end if ; + end if ; + AffirmIf(AlertLogIDVar(Index), CheckCountVar(Index) >= FinishCheckCount, WriteBuf.all & + "Checking CheckCount: " & to_string(CheckCountVar(Index)) & + " >= Expected: " & to_string(FinishCheckCount)) ; + if not (CheckCountVar(Index) >= FinishCheckCount) then + -- Increment internal count on FinishCheckCount Error + ErrCntVar(Index) := ErrCntVar(Index) + 1 ; + end if ; + deallocate(WriteBuf) ; + end procedure CheckFinish ; + + ------------------------------------------------------------ + procedure CheckFinish ( + ------------------------------------------------------------ + FinishCheckCount : integer ; + FinishEmpty : boolean + ) is + begin + for AlertLogID in AlertLogIDVar'range loop + CheckFinish(AlertLogID, FinishCheckCount, FinishEmpty) ; + end loop ; + end procedure CheckFinish ; + + ------------------------------------------------------------ + impure function GetErrorCount (Index : integer) return integer is + ------------------------------------------------------------ + begin + return ErrCntVar(Index) ; + end function GetErrorCount ; + + ------------------------------------------------------------ + impure function GetErrorCount return integer is + ------------------------------------------------------------ + variable TotalErrorCount : integer := 0 ; + begin + for Index in AlertLogIDVar'range loop + TotalErrorCount := TotalErrorCount + GetErrorCount(Index) ; + end loop ; + return TotalErrorCount ; + end function GetErrorCount ; + + ------------------------------------------------------------ + procedure IncErrorCount (Index : integer) is + ------------------------------------------------------------ + begin + ErrCntVar(Index) := ErrCntVar(Index) + 1 ; + IncAlertCount(AlertLogIDVar(Index), ERROR) ; + end IncErrorCount ; + + ------------------------------------------------------------ + procedure IncErrorCount is + ------------------------------------------------------------ + begin + ErrCntVar(FirstIndexVar) := ErrCntVar(FirstIndexVar) + 1 ; + IncAlertCount(AlertLogIDVar(FirstIndexVar), ERROR) ; + end IncErrorCount ; + + ------------------------------------------------------------ + procedure SetErrorCountZero (Index : integer) is + ------------------------------------------------------------ + begin + ErrCntVar(Index) := 0; + end procedure SetErrorCountZero ; + + ------------------------------------------------------------ + procedure SetErrorCountZero is + ------------------------------------------------------------ + begin + ErrCntVar(FirstIndexVar) := 0 ; + end procedure SetErrorCountZero ; + + ------------------------------------------------------------ + impure function GetItemCount (Index : integer) return integer is + ------------------------------------------------------------ + begin + return ItemNumberVar(Index) ; + end function GetItemCount ; + + ------------------------------------------------------------ + impure function GetItemCount return integer is + ------------------------------------------------------------ + begin + return ItemNumberVar(FirstIndexVar) ; + end function GetItemCount ; + + ------------------------------------------------------------ + impure function GetCheckCount (Index : integer) return integer is + ------------------------------------------------------------ + begin + return CheckCountVar(Index) ; + end function GetCheckCount ; + + ------------------------------------------------------------ + impure function GetCheckCount return integer is + ------------------------------------------------------------ + begin + return CheckCountVar(FirstIndexVar) ; + end function GetCheckCount ; + + ------------------------------------------------------------ + impure function GetDropCount (Index : integer) return integer is + ------------------------------------------------------------ + begin + return DropCountVar(Index) ; + end function GetDropCount ; + + ------------------------------------------------------------ + impure function GetDropCount return integer is + ------------------------------------------------------------ + begin + return DropCountVar(FirstIndexVar) ; + end function GetDropCount ; + + ------------------------------------------------------------ + procedure SetFinish ( + ------------------------------------------------------------ + Index : integer ; + FCheckCount : integer ; + FEmpty : boolean := TRUE; + FStatus : boolean := TRUE + ) is + begin + Alert(AlertLogIDVar(Index), "OSVVM.ScoreboardGenericPkg.SetFinish: Deprecated and removed. See CheckFinish", ERROR) ; + end procedure SetFinish ; + + ------------------------------------------------------------ + procedure SetFinish ( + ------------------------------------------------------------ + FCheckCount : integer ; + FEmpty : boolean := TRUE; + FStatus : boolean := TRUE + ) is + begin + SetFinish(FirstIndexVar, FCheckCount, FEmpty, FStatus) ; + end procedure SetFinish ; + + ------------------------------------------------------------ + -- Array of Tagged Scoreboards + -- Find Element with Matching Tag and ActualData + -- Returns integer'left if no match found + impure function Find ( + ------------------------------------------------------------ + constant Index : in integer ; + constant Tag : in string; + constant ActualData : in ActualType + ) return integer is + variable CurPtr : ListPointerType ; + begin + if LocalOutOfRange(Index, "Find") then + return integer'left ; -- error reporting in LocalOutOfRange + end if ; + CurPtr := HeadPointer(Index) ; + loop + if CurPtr = NULL then + -- Failed to find it + ErrCntVar(Index) := ErrCntVar(Index) + 1 ; + if Tag /= "" then + Alert(AlertLogIDVar(Index), + GetName & " Did not find Tag: " & Tag & " and Actual Data: " & actual_to_string(ActualData), + FAILURE ) ; + else + Alert(AlertLogIDVar(Index), + GetName & " Did not find Actual Data: " & actual_to_string(ActualData), + FAILURE ) ; + end if ; + return integer'left ; + + elsif CurPtr.TagPtr.all = Tag and + Match(ActualData, CurPtr.ExpectedPtr.all) then + -- Found it. Return Index. + return CurPtr.ItemNumber ; + + else -- Descend + CurPtr := CurPtr.NextPtr ; + end if ; + end loop ; + end function Find ; + + ------------------------------------------------------------ + -- Array of Simple Scoreboards + -- Find Element with Matching ActualData + impure function Find ( + ------------------------------------------------------------ + constant Index : in integer ; + constant ActualData : in ActualType + ) return integer is + begin + return Find(Index, "", ActualData) ; + end function Find ; + + ------------------------------------------------------------ + -- Tagged Scoreboard + -- Find Element with Matching ActualData + impure function Find ( + ------------------------------------------------------------ + constant Tag : in string; + constant ActualData : in ActualType + ) return integer is + begin + return Find(FirstIndexVar, Tag, ActualData) ; + end function Find ; + + ------------------------------------------------------------ + -- Simple Scoreboard + -- Find Element with Matching ActualData + impure function Find ( + ------------------------------------------------------------ + constant ActualData : in ActualType + ) return integer is + begin + return Find(FirstIndexVar, "", ActualData) ; + end function Find ; + + ------------------------------------------------------------ + -- Array of Tagged Scoreboards + -- Flush Remove elements with tag whose itemNumber is <= ItemNumber parameter + procedure Flush ( + ------------------------------------------------------------ + constant Index : in integer ; + constant Tag : in string ; + constant ItemNumber : in integer + ) is + variable CurPtr, RemovePtr, LastPtr : ListPointerType ; + begin + if LocalOutOfRange(Index, "Find") then + return ; -- error reporting in LocalOutOfRange + end if ; + CurPtr := HeadPointer(Index) ; + LastPtr := NULL ; + loop + if CurPtr = NULL then + -- Done + return ; + elsif CurPtr.TagPtr.all = Tag then + if ItemNumber >= CurPtr.ItemNumber then + -- remove it + RemovePtr := CurPtr ; + if CurPtr = TailPointer(Index) then + TailPointer(Index) := LastPtr ; + end if ; + if CurPtr = HeadPointer(Index) then + HeadPointer(Index) := CurPtr.NextPtr ; + else -- if LastPtr /= NULL then + LastPtr.NextPtr := LastPtr.NextPtr.NextPtr ; + end if ; + CurPtr := CurPtr.NextPtr ; + -- LastPtr := LastPtr ; -- no change + DropCountVar(Index) := DropCountVar(Index) + 1 ; + deallocate(RemovePtr.TagPtr) ; + deallocate(RemovePtr.ExpectedPtr) ; + deallocate(RemovePtr) ; + else + -- Done + return ; + end if ; + else + -- Descend + LastPtr := CurPtr ; + CurPtr := CurPtr.NextPtr ; + end if ; + end loop ; + end procedure Flush ; + + ------------------------------------------------------------ + -- Tagged Scoreboard + -- Flush Remove elements with tag whose itemNumber is <= ItemNumber parameter + procedure Flush ( + ------------------------------------------------------------ + constant Tag : in string ; + constant ItemNumber : in integer + ) is + begin + Flush(FirstIndexVar, Tag, ItemNumber) ; + end procedure Flush ; + + ------------------------------------------------------------ + -- Array of Simple Scoreboards + -- Flush - Remove Elements upto and including the one with ItemNumber + procedure Flush ( + ------------------------------------------------------------ + constant Index : in integer ; + constant ItemNumber : in integer + ) is + variable CurPtr : ListPointerType ; + begin + if LocalOutOfRange(Index, "Find") then + return ; -- error reporting in LocalOutOfRange + end if ; + CurPtr := HeadPointer(Index) ; + loop + if CurPtr = NULL then + -- Done + return ; + elsif ItemNumber >= CurPtr.ItemNumber then + -- Descend, Check Tail, Deallocate + HeadPointer(Index) := HeadPointer(Index).NextPtr ; + if CurPtr = TailPointer(Index) then + TailPointer(Index) := NULL ; + end if ; + DropCountVar(Index) := DropCountVar(Index) + 1 ; + deallocate(CurPtr.TagPtr) ; + deallocate(CurPtr.ExpectedPtr) ; + deallocate(CurPtr) ; + CurPtr := HeadPointer(Index) ; + else + -- Done + return ; + end if ; + end loop ; + end procedure Flush ; + + ------------------------------------------------------------ + -- Simple Scoreboard + -- Flush - Remove Elements upto and including the one with ItemNumber + procedure Flush ( + ------------------------------------------------------------ + constant ItemNumber : in integer + ) is + begin + Flush(FirstIndexVar, ItemNumber) ; + end procedure Flush ; + + ------------------------------------------------------------ + ------------------------------------------------------------ + -- Remaining Deprecated. + ------------------------------------------------------------ + ------------------------------------------------------------ + + ------------------------------------------------------------ + -- Deprecated. Maintained for backward compatibility. + -- Use TranscriptPkg.TranscriptOpen + procedure FileOpen (FileName : string; OpenKind : File_Open_Kind ) is + ------------------------------------------------------------ + begin + -- WriteFileInit := TRUE ; + -- file_open( WriteFile , FileName , OpenKind ); + TranscriptOpen(FileName, OpenKind) ; + end procedure FileOpen ; + + + ------------------------------------------------------------ + -- Deprecated. Maintained for backward compatibility. + procedure PutExpectedData (ExpectedData : ExpectedType) is + ------------------------------------------------------------ + begin + Push(ExpectedData) ; + end procedure PutExpectedData ; + + ------------------------------------------------------------ + -- Deprecated. Maintained for backward compatibility. + procedure CheckActualData (ActualData : ActualType) is + ------------------------------------------------------------ + begin + Check(ActualData) ; + end procedure CheckActualData ; + + ------------------------------------------------------------ + -- Deprecated. Maintained for backward compatibility. + impure function GetItemNumber return integer is + ------------------------------------------------------------ + begin + return GetItemCount(FirstIndexVar) ; + end GetItemNumber ; + + ------------------------------------------------------------ + -- Deprecated. Maintained for backward compatibility. + procedure SetMessage (MessageIn : String) is + ------------------------------------------------------------ + begin + -- deallocate(Message) ; + -- Message := new string'(MessageIn) ; + SetName(MessageIn) ; + end procedure SetMessage ; + + ------------------------------------------------------------ + -- Deprecated. Maintained for backward compatibility. + impure function GetMessage return string is + ------------------------------------------------------------ + begin + -- return Message.all ; + return GetName("Scoreboard") ; + end function GetMessage ; + + end protected body ScoreBoardPType ; +end ScoreboardGenericPkg ; \ No newline at end of file diff --git a/OSVVM/ScoreboardPkg_int.vhd b/OSVVM/ScoreboardPkg_int.vhd new file mode 100644 index 0000000..5d2f3c8 --- /dev/null +++ b/OSVVM/ScoreboardPkg_int.vhd @@ -0,0 +1,65 @@ +-- +-- File Name: ScoreBoardPkg_int.vhd +-- Design Unit Name: ScoreBoardPkg_int +-- Revision: STANDARD VERSION +-- +-- Maintainer: Jim Lewis email: jim@synthworks.com +-- Contributor(s): +-- Jim Lewis email: jim@synthworks.com +-- +-- +-- Description: +-- Instance of Generic Package ScoreboardGenericPkg for integer +-- +-- Developed for: +-- SynthWorks Design Inc. +-- VHDL Training Classes +-- 11898 SW 128th Ave. Tigard, Or 97223 +-- http://www.SynthWorks.com +-- +-- Latest standard version available at: +-- http://www.SynthWorks.com/downloads +-- +-- Revision History: +-- Date Version Description +-- 08/2012 2012.08 Generic Instance of ScoreboardGenericPkg +-- 08/2014 2013.08 Updated interface for Match and to_string +-- 11/2016 2016.11 Released as part of OSVVM library +-- +-- +-- Copyright (c) 2006 - 2016 by SynthWorks Design Inc. All rights reserved. +-- +-- Verbatim copies of this source file may be used and +-- distributed without restriction. +-- +-- This source file is free software; you can redistribute it +-- and/or modify it under the terms of the ARTISTIC License +-- as published by The Perl Foundation; either version 2.0 of +-- the License, or (at your option) any later version. +-- +-- This source is distributed in the hope that it will be +-- useful, but WITHOUT ANY WARRANTY; without even the implied +-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +-- PURPOSE. See the Artistic License for details. +-- +-- You should have received a copy of the license with this source. +-- If not download it from, +-- http://www.perlfoundation.org/artistic_license_2_0 +-- +-- + +use std.textio.all ; + +library ieee ; + use ieee.std_logic_1164.all ; + use ieee.numeric_std.all ; + + +package ScoreBoardPkg_int is new work.ScoreboardGenericPkg + generic map ( + ExpectedType => integer, + ActualType => integer, + Match => "=", + expected_to_string => to_string, + actual_to_string => to_string + ) ; diff --git a/OSVVM/ScoreboardPkg_slv.vhd b/OSVVM/ScoreboardPkg_slv.vhd new file mode 100644 index 0000000..166446a --- /dev/null +++ b/OSVVM/ScoreboardPkg_slv.vhd @@ -0,0 +1,65 @@ +-- +-- File Name: ScoreBoardPkg_slv.vhd +-- Design Unit Name: ScoreBoardPkg_slv +-- Revision: STANDARD VERSION +-- +-- Maintainer: Jim Lewis email: jim@synthworks.com +-- Contributor(s): +-- Jim Lewis email: jim@synthworks.com +-- +-- +-- Description: +-- Instance of Generic Package ScoreboardGenericPkg for std_logic_vector +-- +-- Developed for: +-- SynthWorks Design Inc. +-- VHDL Training Classes +-- 11898 SW 128th Ave. Tigard, Or 97223 +-- http://www.SynthWorks.com +-- +-- Latest standard version available at: +-- http://www.SynthWorks.com/downloads +-- +-- Revision History: +-- Date Version Description +-- 08/2012 2012.08 Generic Instance of ScoreboardGenericPkg +-- 08/2014 2013.08 Updated interface for Match and to_string +-- 11/2016 2016.11 Released as part of OSVVM library +-- +-- +-- Copyright (c) 2006 - 2016 by SynthWorks Design Inc. All rights reserved. +-- +-- Verbatim copies of this source file may be used and +-- distributed without restriction. +-- +-- This source file is free software; you can redistribute it +-- and/or modify it under the terms of the ARTISTIC License +-- as published by The Perl Foundation; either version 2.0 of +-- the License, or (at your option) any later version. +-- +-- This source is distributed in the hope that it will be +-- useful, but WITHOUT ANY WARRANTY; without even the implied +-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +-- PURPOSE. See the Artistic License for details. +-- +-- You should have received a copy of the license with this source. +-- If not download it from, +-- http://www.perlfoundation.org/artistic_license_2_0 +-- +-- + +use std.textio.all ; + +library ieee ; + use ieee.std_logic_1164.all ; + use ieee.numeric_std.all ; + + +package ScoreBoardPkg_slv is new work.ScoreboardGenericPkg + generic map ( + ExpectedType => std_logic_vector, + ActualType => std_logic_vector, + Match => std_match, -- "=", [std_logic_vector, std_logic_vector return boolean] + expected_to_string => to_hstring, -- [std_logic_vector return string] + actual_to_string => to_hstring -- [std_logic_vector return string] + ) ; diff --git a/test/OSVVM/SortListPkg_int.vhd b/OSVVM/SortListPkg_int.vhd old mode 100755 new mode 100644 similarity index 91% rename from test/OSVVM/SortListPkg_int.vhd rename to OSVVM/SortListPkg_int.vhd index c99a73b..6f32151 --- a/test/OSVVM/SortListPkg_int.vhd +++ b/OSVVM/SortListPkg_int.vhd @@ -1,409 +1,417 @@ --- --- File Name: SortListPkg_int.vhd --- Design Unit Name: SortListPkg_int --- Revision: STANDARD VERSION, revision 2014.01 --- --- Maintainer: Jim Lewis email: jim@synthworks.com --- Contributor(s): --- Jim Lewis jim@synthworks.com --- --- Description: --- Sorting utility for array of scalars --- Uses protected type so as to shrink and expand the data structure --- --- Developed for: --- SynthWorks Design Inc. --- VHDL Training Classes --- 11898 SW 128th Ave. Tigard, Or 97223 --- http://www.SynthWorks.com --- --- Revision History: --- Date Version Description --- 06/2008: 0.1 Initial revision --- Numerous revisions for VHDL Testbenches and Verification --- 02/2009: 1.0 First Public Released Version --- 02/25/2009 1.1 Replaced reference to std_2008 with a reference to --- ieee_proposed.standard_additions.all ; --- 06/16/2010 1.2 Added EraseList parameter to to_array --- 3/2011 2.0 added inside as non protected type --- 6/2011 2.1 added sort as non protected type --- 4/2013 2013.04 No Changes --- 5/2013 2013.05 No changes of substance. --- Deleted extra variable declaration in procedure remove --- 1/2014 2014.01 Added RevSort. Added AllowDuplicate paramter to Add procedure --- --- --- --- Copyright (c) 2008 - 2014 by SynthWorks Design Inc. All rights reserved. --- --- Verbatim copies of this source file may be used and --- distributed without restriction. --- --- This source file is free software; you can redistribute it --- and/or modify it under the terms of the ARTISTIC License --- as published by The Perl Foundation; either version 2.0 of --- the License, or (at your option) any later version. --- --- This source is distributed in the hope that it will be --- useful, but WITHOUT ANY WARRANTY; without even the implied --- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR --- PURPOSE. See the Artistic License for details. --- --- You should have received a copy of the license with this source. --- If not download it from, --- http://www.perlfoundation.org/artistic_license_2_0 --- - - use std.textio.all ; - -library ieee ; -use ieee.std_logic_1164.all ; -use ieee.numeric_std.all ; -use ieee.std_logic_textio.all ; - --- comment out following 2 lines with VHDL-2008. Leave in for VHDL-2002 --- library ieee_proposed ; -- remove with VHDL-2008 --- use ieee_proposed.standard_additions.all ; -- remove with VHDL-2008 - - -package SortListPkg_int is - -- with VHDL-2008, convert package to generic package - -- convert subtypes ElementType and ArrayofElementType to generics - -- package SortListGenericPkg is - subtype ElementType is integer ; - subtype ArrayofElementType is integer_vector ; - - function inside (constant E : ElementType; constant A : in ArrayofElementType) return boolean ; - impure function sort (constant A : in ArrayofElementType) return ArrayofElementType ; - impure function revsort (constant A : in ArrayofElementType) return ArrayofElementType ; - - type SortListPType is protected - procedure add ( constant A : in ElementType ; constant AllowDuplicate : Boolean := FALSE ) ; - procedure add ( constant A : in ArrayofElementType ) ; - procedure add ( constant A : in ArrayofElementType ; Min, Max : integer ) ; - procedure add ( variable A : inout SortListPType ) ; - -- Count items in list - impure function count return integer ; - impure function find_index ( constant A : ElementType) return integer ; - impure function inside (constant A : ElementType) return boolean ; - procedure insert ( constant A : in ElementType; constant index : in integer := 1 ) ; - impure function get ( constant index : in integer := 1 ) return ElementType ; - procedure erase ; - impure function Empty return boolean ; - procedure print ; - - procedure remove ( constant A : in ElementType ) ; - procedure remove ( constant A : in ArrayofElementType ) ; - procedure remove ( variable A : inout SortListPType ) ; - - impure function to_array (constant EraseList : boolean := FALSE) return ArrayofElementType ; - impure function to_rev_array (constant EraseList : boolean := FALSE) return ArrayofElementType ; - end protected SortListPType ; - -end SortListPkg_int ; --- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -package body SortListPkg_int is - - function inside (constant E : ElementType; constant A : in ArrayofElementType) return boolean is - begin - for i in A'range loop - if E = A(i) then - return TRUE ; - end if ; - end loop ; - return FALSE ; - end function inside ; - - type SortListPType is protected body - type ListType ; - type ListPointerType is access ListType ; - type ListType is record - A : ElementType ; - -- item_num : integer ; - NextPtr : ListPointerType ; - -- PrevPtr : ListPointerType ; - end record ; - variable HeadPointer : ListPointerType := NULL ; - -- variable TailPointer : ListPointerType := NULL ; - - procedure add ( constant A : in ElementType ; constant AllowDuplicate : Boolean := FALSE ) is - variable CurPtr, tempPtr : ListPointerType ; - begin - if HeadPointer = NULL then - HeadPointer := new ListType'(A, NULL) ; - elsif A = HeadPointer.A then -- ignore duplicates - if AllowDuplicate then - tempPtr := HeadPointer ; - HeadPointer := new ListType'(A, tempPtr) ; - end if ; - elsif A < HeadPointer.A then - tempPtr := HeadPointer ; - HeadPointer := new ListType'(A, tempPtr) ; - else - CurPtr := HeadPointer ; - AddLoop : loop - exit AddLoop when CurPtr.NextPtr = NULL ; - exit AddLoop when A < CurPtr.NextPtr.A ; - if A = CurPtr.NextPtr.A then - if AllowDuplicate then - exit AddLoop ; -- insert - else - return ; -- return without insert - end if; - end if ; - CurPtr := CurPtr.NextPtr ; - end loop AddLoop ; - tempPtr := CurPtr.NextPtr ; - CurPtr.NextPtr := new ListType'(A, tempPtr) ; - end if ; - end procedure add ; - - procedure add ( constant A : in ArrayofElementType ) is - begin - for i in A'range loop - add(A(i)) ; - end loop ; - end procedure add ; - - procedure add ( constant A : in ArrayofElementType ; Min, Max : integer ) is - begin - for i in A'range loop - if A(i) >= Min and A(i) <= Max then - add(A(i)) ; - end if ; - end loop ; - end procedure add ; - - procedure add ( variable A : inout SortListPType ) is - begin - for i in 1 to A.Count loop - add(A.Get(i)) ; - end loop ; - end procedure add ; - - -- Count items in list - impure function count return integer is - variable result : positive := 1 ; - variable CurPtr : ListPointerType ; - begin - if HeadPointer = NULL then - return 0 ; - else - CurPtr := HeadPointer ; - loop - exit when CurPtr.NextPtr = NULL ; - result := result + 1 ; - CurPtr := CurPtr.NextPtr ; - end loop ; - return result ; - end if ; - end function count ; - - impure function find_index (constant A : ElementType) return integer is - variable result : positive := 2 ; - variable CurPtr : ListPointerType ; - begin - if HeadPointer = NULL then - return 0 ; - elsif A <= HeadPointer.A then - return 1 ; - else - CurPtr := HeadPointer ; - loop - exit when CurPtr.NextPtr = NULL ; - exit when A <= CurPtr.NextPtr.A ; - result := result + 1 ; - CurPtr := CurPtr.NextPtr ; - end loop ; - return result ; - end if ; - end function find_index ; - - impure function inside (constant A : ElementType) return boolean is - variable CurPtr : ListPointerType ; - begin - if HeadPointer = NULL then - return FALSE ; - end if ; - if A = HeadPointer.A then - return TRUE ; - else - CurPtr := HeadPointer ; - loop - exit when CurPtr.NextPtr = NULL ; - exit when A < CurPtr.NextPtr.A ; - if A = CurPtr.NextPtr.A then - return TRUE ; -- exit - end if; - CurPtr := CurPtr.NextPtr ; - end loop ; - end if ; - return FALSE ; - end function inside ; - - - procedure insert( constant A : in ElementType; constant index : in integer := 1 ) is - variable CurPtr, tempPtr : ListPointerType ; - begin - if index <= 1 then - tempPtr := HeadPointer ; - HeadPointer := new ListType'(A, tempPtr) ; - else - CurPtr := HeadPointer ; - for i in 3 to index loop - exit when CurPtr.NextPtr = NULL ; -- end of list - CurPtr := CurPtr.NextPtr ; - end loop ; - tempPtr := CurPtr.NextPtr ; - CurPtr.NextPtr := new ListType'(A, tempPtr) ; - end if; - end procedure insert ; - - impure function get ( constant index : in integer := 1 ) return ElementType is - variable CurPtr : ListPointerType ; - begin - if index > Count then - report "%%FAILURE: SortListPType index out of range" severity failure ; - return ElementType'left ; - elsif HeadPointer = NULL then - return ElementType'left ; - elsif index <= 1 then - return HeadPointer.A ; - else - CurPtr := HeadPointer ; - for i in 2 to index loop - CurPtr := CurPtr.NextPtr ; - end loop ; - return CurPtr.A ; - end if; - end function get ; - - - procedure erase (variable CurPtr : inout ListPointerType ) is - begin - if CurPtr.NextPtr /= NULL then - erase (CurPtr.NextPtr) ; - end if ; - deallocate (CurPtr) ; - end procedure erase ; - - procedure erase is - begin - if HeadPointer /= NULL then - erase(HeadPointer) ; - -- deallocate (HeadPointer) ; - HeadPointer := NULL ; - end if; - end procedure erase ; - - impure function Empty return boolean is - begin - return HeadPointer = NULL ; - end Empty ; - - procedure print is - variable buf : line ; - variable CurPtr : ListPointerType ; - begin - if HeadPointer = NULL then - write (buf, string'("( )")) ; - else - CurPtr := HeadPointer ; - write (buf, string'("(")) ; - loop - write (buf, CurPtr.A) ; - exit when CurPtr.NextPtr = NULL ; - write (buf, string'(", ")) ; - CurPtr := CurPtr.NextPtr ; - end loop ; - write (buf, string'(")")) ; - end if ; - writeline(OUTPUT, buf) ; - end procedure print ; - - procedure remove ( constant A : in ElementType ) is - variable CurPtr, tempPtr : ListPointerType ; - begin - if HeadPointer = NULL then - return ; - elsif A = HeadPointer.A then - tempPtr := HeadPointer ; - HeadPointer := HeadPointer.NextPtr ; - deallocate (tempPtr) ; - else - CurPtr := HeadPointer ; - loop - exit when CurPtr.NextPtr = NULL ; - if A = CurPtr.NextPtr.A then - tempPtr := CurPtr.NextPtr ; - CurPtr.NextPtr := CurPtr.NextPtr.NextPtr ; - deallocate (tempPtr) ; - exit ; - end if ; - exit when A < CurPtr.NextPtr.A ; - CurPtr := CurPtr.NextPtr ; - end loop ; - end if ; - end procedure remove ; - - procedure remove ( constant A : in ArrayofElementType ) is - begin - for i in A'range loop - remove(A(i)) ; - end loop ; - end procedure remove ; - - procedure remove ( variable A : inout SortListPType ) is - begin - for i in 1 to A.Count loop - remove(A.Get(i)) ; - end loop ; - end procedure remove ; - - impure function to_array (constant EraseList : boolean := FALSE) return ArrayofElementType is - variable result : ArrayofElementType(1 to Count) ; - begin - for i in 1 to Count loop - result(i) := Get(i) ; - end loop ; - if EraseList then - erase ; - end if ; - return result ; - end function to_array ; - - impure function to_rev_array (constant EraseList : boolean := FALSE) return ArrayofElementType is - variable result : ArrayofElementType(Count downto 1) ; - begin - for i in 1 to Count loop - result(i) := Get(i) ; - end loop ; - if EraseList then - erase ; - end if ; - return result ; - end function to_rev_array ; - - end protected body SortListPType ; - - - impure function sort (constant A : in ArrayofElementType) return ArrayofElementType is - variable Result : SortListPType ; - begin - for i in A'range loop - Result.Add(A(i), TRUE) ; - end loop ; - return Result.to_array(EraseList => TRUE) ; - end function sort ; - - impure function revsort (constant A : in ArrayofElementType) return ArrayofElementType is - variable Result : SortListPType ; - begin - for i in A'range loop - Result.Add(A(i), TRUE) ; - end loop ; - return Result.to_rev_array(EraseList => TRUE) ; - end function revsort ; -end SortListPkg_int ; - +-- +-- File Name: SortListPkg_int.vhd +-- Design Unit Name: SortListPkg_int +-- Revision: STANDARD VERSION +-- +-- Maintainer: Jim Lewis email: jim@synthworks.com +-- Contributor(s): +-- Jim Lewis jim@synthworks.com +-- +-- Description: +-- Sorting utility for array of scalars +-- Uses protected type so as to shrink and expand the data structure +-- +-- Developed for: +-- SynthWorks Design Inc. +-- VHDL Training Classes +-- 11898 SW 128th Ave. Tigard, Or 97223 +-- http://www.SynthWorks.com +-- +-- Revision History: +-- Date Version Description +-- 06/2008: 0.1 Initial revision +-- Numerous revisions for VHDL Testbenches and Verification +-- 02/2009: 1.0 First Public Released Version +-- 02/25/2009 1.1 Replaced reference to std_2008 with a reference to +-- ieee_proposed.standard_additions.all ; +-- 06/16/2010 1.2 Added EraseList parameter to to_array +-- 3/2011 2.0 added inside as non protected type +-- 6/2011 2.1 added sort as non protected type +-- 4/2013 2013.04 No Changes +-- 5/2013 2013.05 No changes of substance. +-- Deleted extra variable declaration in procedure remove +-- 1/2014 2014.01 Added RevSort. Added AllowDuplicate paramter to Add procedure +-- 1/2015 2015.01 Changed Assert/Report to Alert +-- 11/2016 2016.11 Revised Add. When AllowDuplicate, add a matching value last. +-- +-- +-- +-- Copyright (c) 2008 - 2016 by SynthWorks Design Inc. All rights reserved. +-- +-- Verbatim copies of this source file may be used and +-- distributed without restriction. +-- +-- This source file is free software; you can redistribute it +-- and/or modify it under the terms of the ARTISTIC License +-- as published by The Perl Foundation; either version 2.0 of +-- the License, or (at your option) any later version. +-- +-- This source is distributed in the hope that it will be +-- useful, but WITHOUT ANY WARRANTY; without even the implied +-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +-- PURPOSE. See the Artistic License for details. +-- +-- You should have received a copy of the license with this source. +-- If not download it from, +-- http://www.perlfoundation.org/artistic_license_2_0 +-- + +use work.OsvvmGlobalPkg.all ; +use work.AlertLogPkg.all ; +use std.textio.all ; + +library ieee ; +use ieee.std_logic_1164.all ; +use ieee.numeric_std.all ; +use ieee.std_logic_textio.all ; + +-- comment out following 2 lines with VHDL-2008. Leave in for VHDL-2002 +-- library ieee_proposed ; -- remove with VHDL-2008 +-- use ieee_proposed.standard_additions.all ; -- remove with VHDL-2008 + + +package SortListPkg_int is + -- with VHDL-2008, convert package to generic package + -- convert subtypes ElementType and ArrayofElementType to generics + -- package SortListGenericPkg is + subtype ElementType is integer ; + subtype ArrayofElementType is integer_vector ; + + impure function inside (constant E : ElementType; constant A : in ArrayofElementType) return boolean ; + impure function sort (constant A : in ArrayofElementType) return ArrayofElementType ; + impure function revsort (constant A : in ArrayofElementType) return ArrayofElementType ; + + type SortListPType is protected + procedure add ( constant A : in ElementType ; constant AllowDuplicate : Boolean := FALSE ) ; + procedure add ( constant A : in ArrayofElementType ) ; + procedure add ( constant A : in ArrayofElementType ; Min, Max : ElementType ) ; + procedure add ( variable A : inout SortListPType ) ; + -- Count items in list + impure function count return integer ; + impure function find_index ( constant A : ElementType) return integer ; + impure function inside (constant A : ElementType) return boolean ; + procedure insert ( constant A : in ElementType; constant index : in integer := 1 ) ; + impure function get ( constant index : in integer := 1 ) return ElementType ; + procedure erase ; + impure function Empty return boolean ; + procedure print ; + + procedure remove ( constant A : in ElementType ) ; + procedure remove ( constant A : in ArrayofElementType ) ; + procedure remove ( variable A : inout SortListPType ) ; + + impure function to_array (constant EraseList : boolean := FALSE) return ArrayofElementType ; + impure function to_rev_array (constant EraseList : boolean := FALSE) return ArrayofElementType ; + end protected SortListPType ; + +end SortListPkg_int ; + +--- /////////////////////////////////////////////////////////////////////////// +--- /////////////////////////////////////////////////////////////////////////// +--- /////////////////////////////////////////////////////////////////////////// + +package body SortListPkg_int is + + impure function inside (constant E : ElementType; constant A : in ArrayofElementType) return boolean is + begin + for i in A'range loop + if E = A(i) then + return TRUE ; + end if ; + end loop ; + return FALSE ; + end function inside ; + + type SortListPType is protected body + type ListType ; + type ListPointerType is access ListType ; + type ListType is record + A : ElementType ; + -- item_num : integer ; + NextPtr : ListPointerType ; + -- PrevPtr : ListPointerType ; + end record ; + variable HeadPointer : ListPointerType := NULL ; + -- variable TailPointer : ListPointerType := NULL ; + + procedure add ( constant A : in ElementType ; constant AllowDuplicate : Boolean := FALSE ) is + variable CurPtr, tempPtr : ListPointerType ; + begin + if HeadPointer = NULL then + HeadPointer := new ListType'(A, NULL) ; + elsif A = HeadPointer.A then -- ignore duplicates + if AllowDuplicate then + tempPtr := HeadPointer ; + HeadPointer := new ListType'(A, tempPtr) ; + end if ; + elsif A < HeadPointer.A then + tempPtr := HeadPointer ; + HeadPointer := new ListType'(A, tempPtr) ; + else + CurPtr := HeadPointer ; + AddLoop : loop + exit AddLoop when CurPtr.NextPtr = NULL ; + exit AddLoop when A < CurPtr.NextPtr.A ; + if A = CurPtr.NextPtr.A then +-- if AllowDuplicate then -- changed s.t. insert at after match rather than before +-- exit AddLoop ; -- insert +-- else + if not AllowDuplicate then + return ; -- return without insert + end if; + end if ; + CurPtr := CurPtr.NextPtr ; + end loop AddLoop ; + tempPtr := CurPtr.NextPtr ; + CurPtr.NextPtr := new ListType'(A, tempPtr) ; + end if ; + end procedure add ; + + procedure add ( constant A : in ArrayofElementType ) is + begin + for i in A'range loop + add(A(i)) ; + end loop ; + end procedure add ; + + procedure add ( constant A : in ArrayofElementType ; Min, Max : ElementType ) is + begin + for i in A'range loop + if A(i) >= Min and A(i) <= Max then + add(A(i)) ; + end if ; + end loop ; + end procedure add ; + + procedure add ( variable A : inout SortListPType ) is + begin + for i in 1 to A.Count loop + add(A.Get(i)) ; + end loop ; + end procedure add ; + + -- Count items in list + impure function count return integer is + variable result : positive := 1 ; + variable CurPtr : ListPointerType ; + begin + if HeadPointer = NULL then + return 0 ; + else + CurPtr := HeadPointer ; + loop + exit when CurPtr.NextPtr = NULL ; + result := result + 1 ; + CurPtr := CurPtr.NextPtr ; + end loop ; + return result ; + end if ; + end function count ; + + impure function find_index (constant A : ElementType) return integer is + variable result : positive := 2 ; + variable CurPtr : ListPointerType ; + begin + if HeadPointer = NULL then + return 0 ; + elsif A <= HeadPointer.A then + return 1 ; + else + CurPtr := HeadPointer ; + loop + exit when CurPtr.NextPtr = NULL ; + exit when A <= CurPtr.NextPtr.A ; + result := result + 1 ; + CurPtr := CurPtr.NextPtr ; + end loop ; + return result ; + end if ; + end function find_index ; + + impure function inside (constant A : ElementType) return boolean is + variable CurPtr : ListPointerType ; + begin + if HeadPointer = NULL then + return FALSE ; + end if ; + if A = HeadPointer.A then + return TRUE ; + else + CurPtr := HeadPointer ; + loop + exit when CurPtr.NextPtr = NULL ; + exit when A < CurPtr.NextPtr.A ; + if A = CurPtr.NextPtr.A then + return TRUE ; -- exit + end if; + CurPtr := CurPtr.NextPtr ; + end loop ; + end if ; + return FALSE ; + end function inside ; + + + procedure insert( constant A : in ElementType; constant index : in integer := 1 ) is + variable CurPtr, tempPtr : ListPointerType ; + begin + if index <= 1 then + tempPtr := HeadPointer ; + HeadPointer := new ListType'(A, tempPtr) ; + else + CurPtr := HeadPointer ; + for i in 3 to index loop + exit when CurPtr.NextPtr = NULL ; -- end of list + CurPtr := CurPtr.NextPtr ; + end loop ; + tempPtr := CurPtr.NextPtr ; + CurPtr.NextPtr := new ListType'(A, tempPtr) ; + end if; + end procedure insert ; + + impure function get ( constant index : in integer := 1 ) return ElementType is + variable CurPtr : ListPointerType ; + begin + if index > Count then + Alert(OSVVM_ALERTLOG_ID, "SortLIstPkg_int.get index out of range", FAILURE) ; + return ElementType'left ; + elsif HeadPointer = NULL then + return ElementType'left ; + elsif index <= 1 then + return HeadPointer.A ; + else + CurPtr := HeadPointer ; + for i in 2 to index loop + CurPtr := CurPtr.NextPtr ; + end loop ; + return CurPtr.A ; + end if; + end function get ; + + + procedure erase (variable CurPtr : inout ListPointerType ) is + begin + if CurPtr.NextPtr /= NULL then + erase (CurPtr.NextPtr) ; + end if ; + deallocate (CurPtr) ; + end procedure erase ; + + procedure erase is + begin + if HeadPointer /= NULL then + erase(HeadPointer) ; + -- deallocate (HeadPointer) ; + HeadPointer := NULL ; + end if; + end procedure erase ; + + impure function Empty return boolean is + begin + return HeadPointer = NULL ; + end Empty ; + + procedure print is + variable buf : line ; + variable CurPtr : ListPointerType ; + begin + if HeadPointer = NULL then + write (buf, string'("( )")) ; + else + CurPtr := HeadPointer ; + write (buf, string'("(")) ; + loop + write (buf, CurPtr.A) ; + exit when CurPtr.NextPtr = NULL ; + write (buf, string'(", ")) ; + CurPtr := CurPtr.NextPtr ; + end loop ; + write (buf, string'(")")) ; + end if ; + writeline(OUTPUT, buf) ; + end procedure print ; + + procedure remove ( constant A : in ElementType ) is + variable CurPtr, tempPtr : ListPointerType ; + begin + if HeadPointer = NULL then + return ; + elsif A = HeadPointer.A then + tempPtr := HeadPointer ; + HeadPointer := HeadPointer.NextPtr ; + deallocate (tempPtr) ; + else + CurPtr := HeadPointer ; + loop + exit when CurPtr.NextPtr = NULL ; + if A = CurPtr.NextPtr.A then + tempPtr := CurPtr.NextPtr ; + CurPtr.NextPtr := CurPtr.NextPtr.NextPtr ; + deallocate (tempPtr) ; + exit ; + end if ; + exit when A < CurPtr.NextPtr.A ; + CurPtr := CurPtr.NextPtr ; + end loop ; + end if ; + end procedure remove ; + + procedure remove ( constant A : in ArrayofElementType ) is + begin + for i in A'range loop + remove(A(i)) ; + end loop ; + end procedure remove ; + + procedure remove ( variable A : inout SortListPType ) is + begin + for i in 1 to A.Count loop + remove(A.Get(i)) ; + end loop ; + end procedure remove ; + + impure function to_array (constant EraseList : boolean := FALSE) return ArrayofElementType is + variable result : ArrayofElementType(1 to Count) ; + begin + for i in 1 to Count loop + result(i) := Get(i) ; + end loop ; + if EraseList then + erase ; + end if ; + return result ; + end function to_array ; + + impure function to_rev_array (constant EraseList : boolean := FALSE) return ArrayofElementType is + variable result : ArrayofElementType(Count downto 1) ; + begin + for i in 1 to Count loop + result(i) := Get(i) ; + end loop ; + if EraseList then + erase ; + end if ; + return result ; + end function to_rev_array ; + + end protected body SortListPType ; + + + impure function sort (constant A : in ArrayofElementType) return ArrayofElementType is + variable Result : SortListPType ; + begin + for i in A'range loop + Result.Add(A(i), TRUE) ; + end loop ; + return Result.to_array(EraseList => TRUE) ; + end function sort ; + + impure function revsort (constant A : in ArrayofElementType) return ArrayofElementType is + variable Result : SortListPType ; + begin + for i in A'range loop + Result.Add(A(i), TRUE) ; + end loop ; + return Result.to_rev_array(EraseList => TRUE) ; + end function revsort ; +end SortListPkg_int ; + diff --git a/OSVVM/TbUtilPkg.vhd b/OSVVM/TbUtilPkg.vhd new file mode 100644 index 0000000..083d4da --- /dev/null +++ b/OSVVM/TbUtilPkg.vhd @@ -0,0 +1,851 @@ +-- +-- File Name: TbUtilPkg.vhd +-- Design Unit Name: TbUtilPkg +-- Revision: STANDARD VERSION +-- +-- Maintainer: Jim Lewis email: jim@SynthWorks.com +-- Contributor(s): +-- Jim Lewis email: jim@SynthWorks.com +-- +-- Package Defines +-- +-- Developed for: +-- SynthWorks Design Inc. +-- VHDL Training Classes +-- 11898 SW 128th Ave. Tigard, Or 97223 +-- http://www.SynthWorks.com +-- +-- Revision History: +-- Date Version Description +-- 11/1999: 0.1 Initial revision +-- Numerous revisions for VHDL Testbenches and Verification +-- 10/2013 2013.10 Split out Text Utilities +-- 11/2016 2016.11 First Public Release Version +-- Updated naming for consistency. +-- +-- +-- Copyright (c) 1999 - 2016 by SynthWorks Design Inc. All rights reserved. +-- +-- Verbatim copies of this source file may be used and +-- distributed without restriction. +-- +-- This source file is free software; you can redistribute it +-- and/or modify it under the terms of the ARTISTIC License +-- as published by The Perl Foundation; either version 2.0 of +-- the License, or (at your option) any later version. +-- +-- This source is distributed in the hope that it will be +-- useful, but WITHOUT ANY WARRANTY; without even the implied +-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +-- PURPOSE. See the Artistic License for details. +-- +-- You should have received a copy of the license with this source. +-- If not download it from, +-- http://www.perlfoundation.org/artistic_license_2_0 +-- +library ieee ; + use ieee.std_logic_1164.all ; + +library osvvm ; + use osvvm.AlertLogPkg.all ; + use osvvm.TranscriptPkg.all ; + +package TbUtilPkg is + + constant CLK_ACTIVE : std_logic := '1' ; + + constant t_sim_resolution : time := std.env.resolution_limit ; -- VHDL-2008 + -- constant t_sim_resolution : time := 1 ns ; -- for non VHDL-2008 simulators + + ------------------------------------------------------------ + -- ZeroOneHot, OneHot + -- OneHot: return true if exactly one value is 1 + -- ZeroOneHot: return false when more than one value is a 1 + ------------------------------------------------------------ + function OneHot ( constant A : in std_logic_vector ) return boolean ; + function ZeroOneHot ( constant A : in std_logic_vector ) return boolean ; + + + ------------------------------------------------------------ + -- RequestTransaction + -- Transaction initiation side of handshaking + -- Pairs with WaitForTransaction or one of its variations + ------------------------------------------------------------ + procedure RequestTransaction ( + signal Rdy : Out std_logic ; + signal Ack : In std_logic + ) ; + + ------------------------------------------------------------ + -- WaitForTransaction + -- Model side of handshaking + -- Pairs with RequestTransaction + ------------------------------------------------------------ + procedure WaitForTransaction ( + signal Clk : In std_logic ; + signal Rdy : In std_logic ; + signal Ack : Out std_logic + ) ; + + -- Variation for model that stops waiting when TimeOut is asserted + -- Intended for models that need to switch between instruction streams + -- such as a CPU when interrupt is pending + procedure WaitForTransaction ( + signal Clk : In std_logic ; + signal Rdy : In std_logic ; + signal Ack : Out std_logic ; + signal TimeOut : In std_logic ; + constant Polarity : In std_logic := '1' + ) ; + + -- Set Ack to Model starting value + procedure StartTransaction ( signal Ack : Out std_logic ) ; + -- Set Ack to Model finishing value + procedure FinishTransaction ( signal Ack : Out std_logic ) ; + -- If a transaction is pending, return true + function TransactionPending ( signal Rdy : In std_logic ) return boolean ; + + -- Variation for clockless models + procedure WaitForTransaction ( + signal Rdy : In std_logic ; + signal Ack : Out std_logic + ) ; + + + ------------------------------------------------------------ + -- Toggle, WaitForToggle + -- Used for communicating between processes + ------------------------------------------------------------ + procedure Toggle ( + signal Sig : InOut std_logic ; + constant DelayVal : time + ) ; + procedure Toggle ( signal Sig : InOut std_logic ) ; + procedure ToggleHS ( signal Sig : InOut std_logic ) ; + function IsToggle ( signal Sig : In std_logic ) return boolean ; + procedure WaitForToggle ( signal Sig : In std_logic ) ; + + -- Bit type versions + procedure Toggle ( signal Sig : InOut bit ; constant DelayVal : time ) ; + procedure Toggle ( signal Sig : InOut bit ) ; + procedure ToggleHS ( signal Sig : InOut bit ) ; + function IsToggle ( signal Sig : In bit ) return boolean ; + procedure WaitForToggle ( signal Sig : In bit ) ; + + + ------------------------------------------------------------ + -- WaitForBarrier + -- Barrier Synchronization + -- Multiple processes call it, it finishes when all have called it + ------------------------------------------------------------ + procedure WaitForBarrier ( signal Sig : InOut std_logic ) ; + procedure WaitForBarrier ( signal Sig : InOut std_logic ; signal TimeOut : std_logic ; constant Polarity : in std_logic := '1') ; + procedure WaitForBarrier ( signal Sig : InOut std_logic ; constant TimeOut : time ) ; + -- resolved_barrier : summing resolution used in conjunction with integer based barriers + function resolved_barrier ( s : integer_vector ) return integer ; + subtype integer_barrier is resolved_barrier integer ; + -- Usage of integer barriers requires resolved_barrier. Initialization to 1 recommended, but not required + -- signal barrier1 : resolved_barrier integer := 1 ; -- using the resolution function + -- signal barrier2 : integer_barrier := 1 ; -- using the subtype that already applies the resolution function + procedure WaitForBarrier ( signal Sig : InOut integer ) ; + procedure WaitForBarrier ( signal Sig : InOut integer ; signal TimeOut : std_logic ; constant Polarity : in std_logic := '1') ; + procedure WaitForBarrier ( signal Sig : InOut integer ; constant TimeOut : time ) ; + -- Using separate signals + procedure WaitForBarrier2 ( signal SyncOut : out std_logic ; signal SyncIn : in std_logic ) ; + procedure WaitForBarrier2 ( signal SyncOut : out std_logic ; signal SyncInV : in std_logic_vector ) ; + + + ------------------------------------------------------------ + -- WaitForClock + -- Sync to Clock - after a delay, after a number of clocks + ------------------------------------------------------------ + procedure WaitForClock ( signal Clk : in std_logic ; constant Delay : in time ) ; + procedure WaitForClock ( signal Clk : in std_logic ; constant NumberOfClocks : in integer := 1) ; + procedure WaitForClock ( signal Clk : in std_logic ; signal Enable : in boolean ) ; + procedure WaitForClock ( signal Clk : in std_logic ; signal Enable : in std_logic ; constant Polarity : std_logic := '1' ) ; + + + ------------------------------------------------------------ + -- WaitForLevel + -- Find a signal at a level + ------------------------------------------------------------ + procedure WaitForLevel ( signal A : in boolean ) ; + procedure WaitForLevel ( signal A : in std_logic ; Polarity : std_logic := '1' ) ; + + ------------------------------------------------------------ + -- CreateClock, CreateReset + -- Note these do not exit + ------------------------------------------------------------ + procedure CreateClock ( + signal Clk : inout std_logic ; + constant Period : time ; + constant DutyCycle : real := 0.5 + ) ; + + procedure CheckClockPeriod ( + constant AlertLogID : AlertLogIDType ; + signal Clk : in std_logic ; + constant Period : time ; + constant ClkName : string := "Clock" ; + constant HowMany : integer := 5 + ) ; + + procedure CheckClockPeriod ( + signal Clk : in std_logic ; + constant Period : time ; + constant ClkName : string := "Clock" ; + constant HowMany : integer := 5 + ) ; + + procedure CreateReset ( + signal Reset : out std_logic ; + constant ResetActive : in std_logic ; + signal Clk : in std_logic ; + constant Period : time ; + constant tpd : time + ) ; + + procedure LogReset ( + constant AlertLogID : AlertLogIDType ; + signal Reset : in std_logic ; + constant ResetActive : in std_logic ; + constant ResetName : in string := "Reset" ; + constant LogLevel : in LogType := ALWAYS + ) ; + + procedure LogReset ( + signal Reset : in std_logic ; + constant ResetActive : in std_logic ; + constant ResetName : in string := "Reset" ; + constant LogLevel : in LogType := ALWAYS + ) ; + + ------------------------------------------------------------ + -- Deprecated subprogram names + -- Maintaining backward compatibility using aliases + ------------------------------------------------------------ + -- History of RequestTransaction / WaitForTransaction + alias RequestAction is RequestTransaction [std_logic, std_logic] ; + alias WaitForRequest is WaitForTransaction [std_logic, std_logic, std_logic] ; + -- History of WaitForToggle + alias WaitOnToggle is WaitForToggle [std_logic] ; + -- History of WaitForBarrier + alias WayPointBlock is WaitForBarrier [std_logic] ; + alias SyncTo is WaitForBarrier2[std_logic, std_logic] ; + alias SyncTo is WaitForBarrier2[std_logic, std_logic_vector] ; + -- Backward compatible name + alias SyncToClk is WaitForClock [std_logic, time] ; + + ------------------------------------------------------------ + -- Deprecated + -- subsumed by WaitForTransaction with Ack and TimeOut. + -- TimeOut works exactly like IntReq + ------------------------------------------------------------ + procedure WaitForTransactionOrIrq ( + signal Clk : In std_logic ; + signal Rdy : In std_logic ; + signal IntReq : In std_logic + ) ; + + ------------------------------------------------------------ + -- Deprecated + -- WaitForAck, StrobeAck + -- Replaced by WaitForToggle and Toggle + ------------------------------------------------------------ + procedure WaitForAck ( signal Ack : In std_logic ) ; + procedure StrobeAck ( signal Ack : Out std_logic ) ; + +end TbUtilPkg ; + +-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +package body TbUtilPkg is + + ------------------------------------------------------------ + -- ZeroOneHot, OneHot + -- OneHot: return true if exactly one value is 1 + -- ZeroOneHot: return false when more than one value is a 1 + ------------------------------------------------------------ + function OneHot ( constant A : in std_logic_vector ) return boolean is + variable found_one : boolean := FALSE ; + begin + for i in A'range loop + if A(i) = '1' or A(i) = 'H' then + if found_one then + return FALSE ; + end if ; + found_one := TRUE ; + end if ; + end loop ; + return found_one ; -- found a one + end function OneHot ; + + function ZeroOneHot ( constant A : in std_logic_vector ) return boolean is + variable found_one : boolean := FALSE ; + begin + for i in A'range loop + if A(i) = '1' or A(i) = 'H' then + if found_one then + return FALSE ; + end if ; + found_one := TRUE ; + end if ; + end loop ; + return TRUE ; -- all zero or found a one + end function ZeroOneHot ; + + + ------------------------------------------------------------ + -- RequestTransaction + -- Transaction initiation side of handshaking + -- Pairs with WaitForTransaction or one of its variations + ------------------------------------------------------------ + procedure RequestTransaction ( + signal Rdy : Out std_logic ; + signal Ack : In std_logic + ) is + begin + -- Record contains new transaction + Rdy <= '1' ; + -- Find Ack low = '0' + wait until Ack = '0' ; + -- Prepare for Next Transaction + Rdy <= '0' ; + -- Transaction Done + wait until Ack = '1' ; + end procedure ; + + + ------------------------------------------------------------ + -- WaitForTransaction + -- Model side of handshaking + -- Pairs with RequestTransaction + ------------------------------------------------------------ + procedure WaitForTransaction ( + signal Clk : In std_logic ; + signal Rdy : In std_logic ; + signal Ack : Out std_logic + ) is + variable AckTime : time ; + begin + -- End of Previous Cycle. Signal Done + Ack <= '1' ; -- #6 + AckTime := NOW ; + -- Find Start of Transaction + if Rdy /= '1' then -- #2 + wait until Rdy = '1' ; + else + wait for 0 ns ; -- allow Ack to update + end if ; + -- align to clock if needed (not back-to-back transactions) + if NOW /= AckTime then + wait until Clk = CLK_ACTIVE ; + end if ; + -- Model active and owns the record + Ack <= '0' ; -- #3 + end procedure ; + + -- Variation for model that stops waiting when TimeOut is asserted + -- Intended for models that need to switch between instruction streams + -- such as a CPU when interrupt is pending + procedure WaitForTransaction ( + signal Clk : In std_logic ; + signal Rdy : In std_logic ; + signal Ack : Out std_logic ; + signal TimeOut : In std_logic ; + constant Polarity : In std_logic := '1' + ) is + variable AckTime : time ; + variable FoundRdy : boolean ; + begin + -- End of Previous Cycle. Signal Done + Ack <= '1' ; -- #6 + AckTime := NOW ; + -- Find Ready or Time out + if (Rdy /= '1' and TimeOut /= Polarity) then + wait until Rdy = '1' or TimeOut = Polarity ; + else + wait for 0 ns ; -- allow Ack to update + end if ; + FoundRdy := Rdy = '1' ; + -- align to clock if Rdy or TimeOut does not happen within delta cycles from Ack + if NOW /= AckTime then + wait until Clk = CLK_ACTIVE ; + end if ; + if FoundRdy then + -- Model active and owns the record + Ack <= '0' ; -- #3 + end if ; + end procedure ; + + -- Set Ack to Model starting value + -- Pairs with WaitForTransactionOrIrq above + procedure StartTransaction ( signal Ack : Out std_logic ) is + begin + Ack <= '0' ; + end procedure ; + + -- Set Ack to Model finishing value + -- Pairs with WaitForTransactionOrIrq above + procedure FinishTransaction ( signal Ack : Out std_logic ) is + begin + -- End of Cycle + Ack <= '1' ; + end procedure ; + + -- If a transaction is pending, return true + -- Used to detect presence of transaction stream, + -- such as an interrupt handler + function TransactionPending ( + signal Rdy : In std_logic + ) return boolean is + begin + return Rdy = '1' ; + end function ; + + -- Variation for clockless models + procedure WaitForTransaction ( + signal Rdy : In std_logic ; + signal Ack : Out std_logic + ) is + variable AckTime : time ; + begin + -- End of Previous Cycle. Signal Done + Ack <= '1' ; -- #6 + -- Find Start of Transaction + if Rdy /= '1' then -- #2 + wait until Rdy = '1' ; + else + wait for 0 ns ; -- allow Ack to update + end if ; + -- Model active and owns the record + Ack <= '0' ; -- #3 + end procedure ; + + + ------------------------------------------------------------ + -- Toggle, WaitForToggle + -- Used for communicating between processes + ------------------------------------------------------------ + type stdulogic_indexby_stdulogic is array (std_ulogic) of std_ulogic; + constant toggle_sl_table : stdulogic_indexby_stdulogic := ( + '0' => '1', + 'L' => '1', + others => '0' + ); + + procedure Toggle ( + signal Sig : InOut std_logic ; + constant DelayVal : time + ) is + variable iDelayVal : time ; + begin + iDelayVal := DelayVal ; + if iDelayVal > t_sim_resolution then + iDelayVal := iDelayVal - t_sim_resolution ; + end if ; + Sig <= toggle_sl_table(Sig) after iDelayVal ; + end procedure ; + + procedure Toggle ( signal Sig : InOut std_logic ) is + begin + Sig <= toggle_sl_table(Sig) ; + end procedure ; + + procedure ToggleHS ( signal Sig : InOut std_logic ) is + begin + Sig <= toggle_sl_table(Sig) ; + wait for 0 ns ; -- Sig toggles + wait for 0 ns ; -- new values updated into record + end procedure ; + + function IsToggle ( signal Sig : In std_logic ) return boolean is + begin + return Sig'event ; + end function ; + + procedure WaitForToggle ( signal Sig : In std_logic ) is + begin + wait on Sig ; + end procedure ; + + -- Bit type versions + procedure Toggle ( signal Sig : InOut bit ; constant DelayVal : time ) is + variable iDelayVal : time ; + begin + iDelayVal := DelayVal ; + if iDelayVal > t_sim_resolution then + iDelayVal := iDelayVal - t_sim_resolution ; + end if ; + Sig <= not Sig after iDelayVal ; + end procedure ; + + procedure Toggle ( signal Sig : InOut bit ) is + begin + Sig <= not Sig ; + end procedure ; + + procedure ToggleHS ( signal Sig : InOut bit ) is + begin + Sig <= not Sig ; + wait for 0 ns ; -- Sig toggles + wait for 0 ns ; -- new values updated into record + end procedure ; + + function IsToggle ( signal Sig : In bit ) return boolean is + begin + return Sig'event ; + end function ; + + procedure WaitForToggle ( signal Sig : In bit ) is + begin + wait on Sig ; + end procedure ; + + + ------------------------------------------------------------ + -- WaitForBarrier + -- Barrier Synchronization + -- Multiple processes call it, it finishes when all have called it + ------------------------------------------------------------ + procedure WaitForBarrier ( signal Sig : InOut std_logic ) is + begin + Sig <= 'H' ; + -- Wait until all processes set Sig to H + -- Level check not necessary since last value /= H yet + wait until Sig = 'H' ; + -- Deactivate and propagate to allow back to back calls + Sig <= '0' ; + wait for 0 ns ; + end procedure WaitForBarrier ; + + procedure WaitForBarrier ( signal Sig : InOut std_logic ; signal TimeOut : std_logic ; constant Polarity : in std_logic := '1') is + begin + Sig <= 'H' ; + -- Wait until all processes set Sig to H + -- Level check not necessary since last value /= H yet + wait until Sig = 'H' or TimeOut = Polarity ; + -- Deactivate and propagate to allow back to back calls + Sig <= '0' ; + wait for 0 ns ; + end procedure WaitForBarrier ; + + procedure WaitForBarrier ( signal Sig : InOut std_logic ; constant TimeOut : time ) is + begin + Sig <= 'H' ; + -- Wait until all processes set Sig to H + -- Level check not necessary since last value /= H yet + wait until Sig = 'H' for TimeOut ; + -- Deactivate and propagate to allow back to back calls + Sig <= '0' ; + wait for 0 ns ; + end procedure WaitForBarrier ; + + ------------------------------------------------------------ + -- resolved_barrier + -- summing resolution used in conjunction with integer based barriers + function resolved_barrier ( s : integer_vector ) return integer is + variable result : integer := 0 ; + begin + for i in s'RANGE loop + if s(i) /= integer'left then + result := s(i) + result; + else + return integer'left ; -- removes the initialization requirement + end if ; + end loop ; + return result ; + end function resolved_barrier ; + + -- Usage of integer barriers requires resolved_barrier. Initialization to 1 recommended, but not required + -- signal barrier1 : resolved_barrier integer := 1 ; -- using the resolution function + -- signal barrier2 : integer_barrier := 1 ; -- using the subtype that already applies the resolution function + procedure WaitForBarrier ( signal Sig : InOut integer ) is + begin + Sig <= 0 ; + -- Wait until all processes set Sig to 0 + -- Level check not necessary since last value /= 0 yet + wait until Sig = 0 ; + -- Deactivate and propagate to allow back to back calls + Sig <= 1 ; + wait for 0 ns ; + end procedure WaitForBarrier ; + + procedure WaitForBarrier ( signal Sig : InOut integer ; signal TimeOut : std_logic ; constant Polarity : in std_logic := '1') is + begin + Sig <= 0 ; + -- Wait until all processes set Sig to 0 + -- Level check not necessary since last value /= 0 yet + wait until Sig = 0 or TimeOut = Polarity ; + -- Deactivate and propagate to allow back to back calls + Sig <= 1 ; + wait for 0 ns ; + end procedure WaitForBarrier ; + + procedure WaitForBarrier ( signal Sig : InOut integer ; constant TimeOut : time ) is + begin + Sig <= 0 ; + -- Wait until all processes set Sig to 0 + -- Level check not necessary since last value /= 0 yet + wait until Sig = 0 for TimeOut ; + -- Deactivate and propagate to allow back to back calls + Sig <= 1 ; + wait for 0 ns ; + end procedure WaitForBarrier ; + + -- Using separate signals + procedure WaitForBarrier2 ( signal SyncOut : out std_logic ; signal SyncIn : in std_logic ) is + begin + -- Activate Rdy + SyncOut <= '1' ; + -- Make sure our Rdy is seen + wait for 0 ns ; + -- Wait until other process' Rdy is at level 1 + if SyncIn /= '1' then + wait until SyncIn = '1' ; + end if ; + -- Deactivate Rdy + SyncOut <= '0' ; + end procedure WaitForBarrier2 ; + + procedure WaitForBarrier2 ( signal SyncOut : out std_logic ; signal SyncInV : in std_logic_vector ) is + constant ALL_ONE : std_logic_vector(SyncInV'Range) := (others => '1'); + begin + -- Activate Rdy + SyncOut <= '1' ; + -- Make sure our Rdy is seen + wait for 0 ns ; + -- Wait until all other process' Rdy is at level 1 + if SyncInV /= ALL_ONE then + wait until SyncInV = ALL_ONE ; + end if ; + -- Deactivate Rdy + SyncOut <= '0' ; + end procedure WaitForBarrier2 ; + + + ------------------------------------------------------------ + -- WaitForClock + -- Sync to Clock - after a delay, after a number of clocks + ------------------------------------------------------------ + procedure WaitForClock ( signal Clk : in std_logic ; constant Delay : in time ) is + begin + if delay > t_sim_resolution then + wait for delay - t_sim_resolution ; + end if ; + wait until Clk = CLK_ACTIVE ; + end procedure WaitForClock ; + + procedure WaitForClock ( signal Clk : in std_logic ; constant NumberOfClocks : in integer := 1) is + begin + for i in 1 to NumberOfClocks loop + wait until Clk = CLK_ACTIVE ; + end loop ; + end procedure WaitForClock ; + + procedure WaitForClock ( signal Clk : in std_logic ; signal Enable : in boolean ) is + begin + wait on Clk until Clk = CLK_ACTIVE and Enable ; + end procedure WaitForClock ; + + procedure WaitForClock ( signal Clk : in std_logic ; signal Enable : in std_logic ; constant Polarity : std_logic := '1' ) is + begin + wait on Clk until Clk = CLK_ACTIVE and Enable = Polarity ; + end procedure WaitForClock ; + + + ------------------------------------------------------------ + -- WaitForLevel + -- Find a signal at a level + ------------------------------------------------------------ + procedure WaitForLevel ( signal A : in boolean ) is + begin + if not A then + wait until A ; + end if ; + end procedure WaitForLevel ; + + procedure WaitForLevel ( signal A : in std_logic ; Polarity : std_logic := '1' ) is + begin + if A /= Polarity then + -- wait on A until A = Polarity ; + if Polarity = '1' then + wait until A = '1' ; + else + wait until A = '0' ; + end if ; + end if ; + end procedure WaitForLevel ; + + + ------------------------------------------------------------ + -- CreateClock, CreateReset + -- Note these do not exit + ------------------------------------------------------------ + procedure CreateClock ( + signal Clk : inout std_logic ; + constant Period : time ; + constant DutyCycle : real := 0.5 + ) is + constant HIGH_TIME : time := Period * DutyCycle ; + constant LOW_TIME : time := Period - HIGH_TIME ; + begin + if HIGH_TIME = LOW_TIME then + loop + Clk <= toggle_sl_table(Clk) after HIGH_TIME ; + wait on Clk ; + end loop ; + else + -- Schedule s.t. all assignments after the first occur on delta cycle 0 + Clk <= '0', '1' after LOW_TIME ; + wait for period - 1 ns ; -- allows after on future Clk <= '0' + loop + Clk <= '0' after 1 ns, '1' after LOW_TIME + 1 ns ; + wait for period ; + end loop ; + end if ; + end procedure CreateClock ; + + procedure CheckClockPeriod ( + constant AlertLogID : AlertLogIDType ; + signal Clk : in std_logic ; + constant Period : time ; + constant ClkName : string := "Clock" ; + constant HowMany : integer := 5 + ) is + variable LastLogTime, ObservedPeriod : time ; + begin + wait until Clk = CLK_ACTIVE ; + LastLogTime := now ; + -- Check First HowMany clocks + for i in 1 to HowMany loop + wait until Clk = CLK_ACTIVE ; + ObservedPeriod := now - LastLogTime ; + AffirmIf(AlertLogID, ObservedPeriod = Period, + "CheckClockPeriod: " & ClkName & " Period: " & to_string(ObservedPeriod) & + " = Expected " & to_string(Period)) ; + LastLogTime := now ; + end loop ; + wait ; + end procedure CheckClockPeriod ; + + procedure CheckClockPeriod ( + signal Clk : in std_logic ; + constant Period : time ; + constant ClkName : string := "Clock" ; + constant HowMany : integer := 5 + ) is + begin + CheckClockPeriod ( + AlertLogID => ALERTLOG_DEFAULT_ID, + Clk => Clk, + Period => Period, + ClkName => ClkName, + HowMany => HowMany + ) ; + end procedure CheckClockPeriod ; + + procedure CreateReset ( + signal Reset : out std_logic ; + constant ResetActive : in std_logic ; + signal Clk : in std_logic ; + constant Period : time ; + constant tpd : time + ) is + begin + wait until Clk = CLK_ACTIVE ; + Reset <= ResetActive after tpd ; + wait for Period - t_sim_resolution ; + wait until Clk = CLK_ACTIVE ; + Reset <= not ResetActive after tpd ; + wait ; + end procedure CreateReset ; + + procedure LogReset ( + constant AlertLogID : AlertLogIDType ; + signal Reset : in std_logic ; + constant ResetActive : in std_logic ; + constant ResetName : in string := "Reset" ; + constant LogLevel : in LogType := ALWAYS + ) is + begin + -- Does not log the value of Reset at time 0. + for_ever : loop + wait on Reset ; + if Reset = ResetActive then + LOG(AlertLogID, ResetName & " now active", INFO) ; + print("") ; + elsif Reset = not ResetActive then + LOG(AlertLogID, ResetName & " now inactive", INFO) ; + print("") ; + else + LOG(AlertLogID, ResetName & " = " & to_string(Reset), INFO) ; + print("") ; + end if ; + end loop for_ever ; + end procedure LogReset ; + + procedure LogReset ( + signal Reset : in std_logic ; + constant ResetActive : in std_logic ; + constant ResetName : in string := "Reset" ; + constant LogLevel : in LogType := ALWAYS + ) is + begin + LogReset ( + AlertLogID => ALERTLOG_DEFAULT_ID, + Reset => Reset, + ResetActive => ResetActive, + ResetName => ResetName, + LogLevel => LogLevel + ) ; + end procedure LogReset ; + + ------------------------------------------------------------ + -- Deprecated + -- subsumed by WaitForTransaction with Ack and TimeOut. + -- TimeOut works exactly like IntReq + ------------------------------------------------------------ + procedure WaitForTransactionOrIrq ( + signal Clk : In std_logic ; + signal Rdy : In std_logic ; + signal IntReq : In std_logic + ) is + variable AckTime : time ; + constant POLARITY : std_logic := '1' ; + begin + AckTime := NOW ; + -- Find Ready or Time out + if (Rdy /= '1' and IntReq /= POLARITY) then + wait until Rdy = '1' or IntReq = POLARITY ; + else + wait for 0 ns ; -- allow Ack to update + end if ; + -- align to clock if Rdy or IntReq does not happen within delta cycles from Ack + if NOW /= AckTime then + wait until Clk = CLK_ACTIVE ; + end if ; + end procedure ; + + ------------------------------------------------------------ + -- Deprecated + -- WaitForAck, StrobeAck + -- Replaced by WaitForToggle and Toggle + ------------------------------------------------------------ + procedure WaitForAck ( signal Ack : In std_logic ) is + begin + -- Wait for Model to be done + wait until Ack = '1' ; + end procedure ; + + procedure StrobeAck ( signal Ack : Out std_logic ) is + begin + -- Model done, drive rising edge on Ack + Ack <= '0' ; + wait for 0 ns ; + Ack <= '1' ; + end procedure ; + + +end TbUtilPkg ; + diff --git a/OSVVM/TextUtilPkg.vhd b/OSVVM/TextUtilPkg.vhd new file mode 100644 index 0000000..d1c5ee1 --- /dev/null +++ b/OSVVM/TextUtilPkg.vhd @@ -0,0 +1,407 @@ +-- +-- File Name: TextUtilPkg.vhd +-- Design Unit Name: TextUtilPkg +-- Revision: STANDARD VERSION +-- +-- Maintainer: Jim Lewis email: jim@synthworks.com +-- Contributor(s): +-- Jim Lewis jim@synthworks.com +-- +-- +-- Description: +-- Shared Utilities for handling text files +-- +-- +-- Developed for: +-- SynthWorks Design Inc. +-- VHDL Training Classes +-- 11898 SW 128th Ave. Tigard, Or 97223 +-- http://www.SynthWorks.com +-- +-- Revision History: +-- Date Version Description +-- 01/2015: 2015.05 Initial revision +-- 01/2016: 2016.01 Update for L.all(L'left) +-- 11/2016: 2016.11 Added IsUpper, IsLower, to_upper, to_lower +-- +-- +-- Copyright (c) 2015-2016 by SynthWorks Design Inc. All rights reserved. +-- +-- Verbatim copies of this source file may be used and +-- distributed without restriction. +-- +-- This source file is free software; you can redistribute it +-- and/or modify it under the terms of the ARTISTIC License +-- as published by The Perl Foundation; either version 2.0 of +-- the License, or (at your option) any later version. +-- +-- This source is distributed in the hope that it will be +-- useful, but WITHOUT ANY WARRANTY; without even the implied +-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +-- PURPOSE. See the Artistic License for details. +-- +-- You should have received a copy of the license with this source. +-- If not download it from, +-- http://www.perlfoundation.org/artistic_license_2_0 +-- + +use std.textio.all ; +library ieee ; +use ieee.std_logic_1164.all ; + +package TextUtilPkg is + ------------------------------------------------------------ + function IsUpper (constant Char : character ) return boolean ; + function IsLower (constant Char : character ) return boolean ; + function to_lower (constant Char : character ) return character ; + function to_lower (constant Str : string ) return string ; + function to_upper (constant Char : character ) return character ; + function to_upper (constant Str : string ) return string ; + function ishex (constant Char : character ) return boolean ; + function isstd_logic (constant Char : character ) return boolean ; + + ------------------------------------------------------------ + procedure SkipWhiteSpace ( + ------------------------------------------------------------ + variable L : InOut line ; + variable Empty : out boolean + ) ; + procedure SkipWhiteSpace (variable L : InOut line) ; + + ------------------------------------------------------------ + procedure EmptyOrCommentLine ( + ------------------------------------------------------------ + variable L : InOut line ; + variable Empty : InOut boolean ; + variable MultiLineComment : inout boolean + ) ; + + ------------------------------------------------------------ + procedure ReadHexToken ( + -- Reads Upto Result'length values, less is ok. + -- Does not skip white space + ------------------------------------------------------------ + variable L : InOut line ; + variable Result : Out std_logic_vector ; + variable StrLen : Out integer + ) ; + + ------------------------------------------------------------ + procedure ReadBinaryToken ( + -- Reads Upto Result'length values, less is ok. + -- Does not skip white space + ------------------------------------------------------------ + variable L : InOut line ; + variable Result : Out std_logic_vector ; + variable StrLen : Out integer + ) ; + +end TextUtilPkg ; + +--- /////////////////////////////////////////////////////////////////////////// +--- /////////////////////////////////////////////////////////////////////////// +--- /////////////////////////////////////////////////////////////////////////// + +package body TextUtilPkg is + constant LOWER_TO_UPPER_OFFSET : integer := character'POS('a') - character'POS('A') ; + + ------------------------------------------------------------ + function "-" (R : character ; L : integer ) return character is + ------------------------------------------------------------ + begin + return character'VAL(character'pos(R) - L) ; + end function "-" ; + + ------------------------------------------------------------ + function "+" (R : character ; L : integer ) return character is + ------------------------------------------------------------ + begin + return character'VAL(character'pos(R) + L) ; + end function "+" ; + + ------------------------------------------------------------ + function IsUpper (constant Char : character ) return boolean is + ------------------------------------------------------------ + begin + if Char >= 'A' and Char <= 'Z' then + return TRUE ; + else + return FALSE ; + end if ; + end function IsUpper ; + + ------------------------------------------------------------ + function IsLower (constant Char : character ) return boolean is + ------------------------------------------------------------ + begin + if Char >= 'a' and Char <= 'z' then + return TRUE ; + else + return FALSE ; + end if ; + end function IsLower ; + + ------------------------------------------------------------ + function to_lower (constant Char : character ) return character is + ------------------------------------------------------------ + begin + if IsUpper(Char) then + return Char + LOWER_TO_UPPER_OFFSET ; + else + return Char ; + end if ; + end function to_lower ; + + ------------------------------------------------------------ + function to_lower (constant Str : string ) return string is + ------------------------------------------------------------ + variable result : string(Str'range) ; + begin + for i in Str'range loop + result(i) := to_lower(Str(i)) ; + end loop ; + return result ; + end function to_lower ; + + ------------------------------------------------------------ + function to_upper (constant Char : character ) return character is + ------------------------------------------------------------ + begin + if IsLower(Char) then + return Char - LOWER_TO_UPPER_OFFSET ; + else + return Char ; + end if ; + end function to_upper ; + + ------------------------------------------------------------ + function to_upper (constant Str : string ) return string is + ------------------------------------------------------------ + variable result : string(Str'range) ; + begin + for i in Str'range loop + result(i) := to_upper(Str(i)) ; + end loop ; + return result ; + end function to_upper ; + + ------------------------------------------------------------ + function ishex (constant Char : character ) return boolean is + ------------------------------------------------------------ + begin + if Char >= '0' and Char <= '9' then + return TRUE ; + elsif Char >= 'a' and Char <= 'f' then + return TRUE ; + elsif Char >= 'A' and Char <= 'F' then + return TRUE ; + else + return FALSE ; + end if ; + end function ishex ; + + ------------------------------------------------------------ + function isstd_logic (constant Char : character ) return boolean is + ------------------------------------------------------------ + begin + case Char is + when 'U' | 'X' | '0' | '1' | 'Z' | 'W' | 'L' | 'H' | '-' => + return TRUE ; + when others => + return FALSE ; + end case ; + end function isstd_logic ; + +-- ------------------------------------------------------------ +-- function iscomment (constant Char : character ) return boolean is +-- ------------------------------------------------------------ +-- begin +-- case Char is +-- when '#' | '/' | '-' => +-- return TRUE ; +-- when others => +-- return FALSE ; +-- end case ; +-- end function iscomment ; + + ------------------------------------------------------------ + procedure SkipWhiteSpace ( + ------------------------------------------------------------ + variable L : InOut line ; + variable Empty : out boolean + ) is + variable Valid : boolean ; + variable Char : character ; + constant NBSP : CHARACTER := CHARACTER'val(160); -- space character + begin + Empty := TRUE ; + WhiteSpLoop : while L /= null and L.all'length > 0 loop + if (L.all(L'left) = ' ' or L.all(L'left) = NBSP or L.all(L'left) = HT) then + read (L, Char, Valid) ; + exit when not Valid ; + else + Empty := FALSE ; + return ; + end if ; + end loop WhiteSpLoop ; + end procedure SkipWhiteSpace ; + + ------------------------------------------------------------ + procedure SkipWhiteSpace ( + ------------------------------------------------------------ + variable L : InOut line + ) is + variable Empty : boolean ; + begin + SkipWhiteSpace(L, Empty) ; + end procedure SkipWhiteSpace ; + + ------------------------------------------------------------ + -- Package Local + procedure FindCommentEnd ( + ------------------------------------------------------------ + variable L : InOut line ; + variable Empty : out boolean ; + variable MultiLineComment : inout boolean + ) is + variable Valid : boolean ; + variable Char : character ; + begin + MultiLineComment := TRUE ; + Empty := TRUE ; + FindEndOfCommentLoop : while L /= null and L.all'length > 1 loop + read(L, Char, Valid) ; + if Char = '*' and L.all(L'left) = '/' then + read(L, Char, Valid) ; + Empty := FALSE ; + MultiLineComment := FALSE ; + exit FindEndOfCommentLoop ; + end if ; + end loop ; + end procedure FindCommentEnd ; + + ------------------------------------------------------------ + procedure EmptyOrCommentLine ( + ------------------------------------------------------------ + variable L : InOut line ; + variable Empty : InOut boolean ; + variable MultiLineComment : inout boolean + ) is + variable Valid : boolean ; + variable Next2Char : string(1 to 2) ; + constant NBSP : CHARACTER := CHARACTER'val(160); -- space character + begin + if MultiLineComment then + FindCommentEnd(L, Empty, MultiLineComment) ; + end if ; + + EmptyCheckLoop : while not MultiLineComment loop + SkipWhiteSpace(L, Empty) ; + exit when Empty ; -- line null or 0 in length detected by SkipWhite + + Empty := TRUE ; + + exit when L.all(L'left) = '#' ; -- shell style comment + + if L.all'length >= 2 then + if L'ascending then + Next2Char := L.all(L'left to L'left+1) ; + else + Next2Char := L.all(L'left to L'left-1) ; + end if; + exit when Next2Char = "//" ; -- C style comment + exit when Next2Char = "--" ; -- VHDL style comment + + if Next2Char = "/*" then -- C style multi line comment + FindCommentEnd(L, Empty, MultiLineComment) ; + exit when Empty ; + next EmptyCheckLoop ; -- Found end of comment, restart processing line + end if ; + end if ; + + Empty := FALSE ; + exit ; + end loop EmptyCheckLoop ; + end procedure EmptyOrCommentLine ; + + ------------------------------------------------------------ + procedure ReadHexToken ( + -- Reads Upto Result'length values, less is ok. + -- Does not skip white space + ------------------------------------------------------------ + variable L : InOut line ; + variable Result : Out std_logic_vector ; + variable StrLen : Out integer + ) is + constant NumHexChars : integer := (Result'length+3)/4 ; + constant ResultNormLen : integer := NumHexChars * 4 ; + variable NextChar : character ; + variable CharCount : integer ; + variable ReturnVal : std_logic_vector(ResultNormLen-1 downto 0) ; + variable ReadVal : std_logic_vector(3 downto 0) ; + variable ReadValid : boolean ; + begin + ReturnVal := (others => '0') ; + CharCount := 0 ; + + ReadLoop : while L /= null and L.all'length > 0 loop + NextChar := L.all(L'left) ; + if ishex(NextChar) or NextChar = 'X' or NextChar = 'Z' then + hread(L, ReadVal, ReadValid) ; + ReturnVal := ReturnVal(ResultNormLen-5 downto 0) & ReadVal ; + CharCount := CharCount + 1 ; + exit ReadLoop when CharCount >= NumHexChars ; + elsif NextChar = '_' then + read(L, NextChar, ReadValid) ; + else + exit ; + end if ; + end loop ReadLoop ; + + if CharCount >= NumHexChars then + StrLen := Result'length ; + else + StrLen := CharCount * 4 ; + end if ; + + Result := ReturnVal(Result'length-1 downto 0) ; + end procedure ReadHexToken ; + + ------------------------------------------------------------ + procedure ReadBinaryToken ( + -- Reads Upto Result'length values, less is ok. + -- Does not skip white space + ------------------------------------------------------------ + variable L : InOut line ; + variable Result : Out std_logic_vector ; + variable StrLen : Out integer + ) is + variable NextChar : character ; + variable CharCount : integer ; + variable ReadVal : std_logic ; + variable ReturnVal : std_logic_vector(Result'length-1 downto 0) ; + variable ReadValid : boolean ; + begin + ReturnVal := (others => '0') ; + CharCount := 0 ; + + ReadLoop : while L /= null and L.all'length > 0 loop + NextChar := L.all(L'left) ; + if isstd_logic(NextChar) then + read(L, ReadVal, ReadValid) ; + ReturnVal := ReturnVal(Result'length-2 downto 0) & ReadVal ; + CharCount := CharCount + 1 ; + exit ReadLoop when CharCount >= Result'length ; + elsif NextChar = '_' then + read(L, NextChar, ReadValid) ; + else + exit ; + end if ; + end loop ReadLoop ; + + StrLen := CharCount ; + Result := ReturnVal ; + end procedure ReadBinaryToken ; + + +end package body TextUtilPkg ; \ No newline at end of file diff --git a/OSVVM/TranscriptPkg.vhd b/OSVVM/TranscriptPkg.vhd new file mode 100644 index 0000000..a88b00a --- /dev/null +++ b/OSVVM/TranscriptPkg.vhd @@ -0,0 +1,200 @@ +-- +-- File Name: TranscriptPkg.vhd +-- Design Unit Name: TranscriptPkg +-- Revision: STANDARD VERSION +-- +-- Maintainer: Jim Lewis email: jim@synthworks.com +-- Contributor(s): +-- Jim Lewis jim@synthworks.com +-- +-- +-- Description: +-- Define file identifier TranscriptFile +-- provide subprograms to open, close, and print to it. +-- +-- +-- Developed for: +-- SynthWorks Design Inc. +-- VHDL Training Classes +-- 11898 SW 128th Ave. Tigard, Or 97223 +-- http://www.SynthWorks.com +-- +-- Revision History: +-- Date Version Description +-- 01/2015: 2015.01 Initial revision +-- 01/2016: 2016.01 TranscriptOpen function now calls procedure of same name +-- 11/2016: 2016.l1 Added procedure BlankLine +-- +-- +-- Copyright (c) 2015-2016 by SynthWorks Design Inc. All rights reserved. +-- +-- Verbatim copies of this source file may be used and +-- distributed without restriction. +-- +-- This source file is free software; you can redistribute it +-- and/or modify it under the terms of the ARTISTIC License +-- as published by The Perl Foundation; either version 2.0 of +-- the License, or (at your option) any later version. +-- +-- This source is distributed in the hope that it will be +-- useful, but WITHOUT ANY WARRANTY; without even the implied +-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +-- PURPOSE. See the Artistic License for details. +-- +-- You should have received a copy of the license with this source. +-- If not download it from, +-- http://www.perlfoundation.org/artistic_license_2_0 +-- + +use std.textio.all ; +package TranscriptPkg is + + -- File Identifier to facilitate usage of one transcript file + file TranscriptFile : text ; + + -- Cause compile errors if READ_MODE is passed to TranscriptOpen + subtype WRITE_APPEND_OPEN_KIND is FILE_OPEN_KIND range WRITE_MODE to APPEND_MODE ; + + -- Open and close TranscriptFile. Function allows declarative opens + procedure TranscriptOpen (Status: out FILE_OPEN_STATUS; ExternalName: STRING; OpenKind: WRITE_APPEND_OPEN_KIND := WRITE_MODE) ; + procedure TranscriptOpen (ExternalName: STRING; OpenKind: WRITE_APPEND_OPEN_KIND := WRITE_MODE) ; + impure function TranscriptOpen (ExternalName: STRING; OpenKind: WRITE_APPEND_OPEN_KIND := WRITE_MODE) return FILE_OPEN_STATUS ; + + procedure TranscriptClose ; + impure function IsTranscriptOpen return boolean ; + alias IsTranscriptEnabled is IsTranscriptOpen [return boolean] ; + + -- Mirroring. When using TranscriptPkw WriteLine and Print, uses both TranscriptFile and OUTPUT + procedure SetTranscriptMirror (A : boolean := TRUE) ; + impure function IsTranscriptMirrored return boolean ; + alias GetTranscriptMirror is IsTranscriptMirrored [return boolean] ; + + -- Write to TranscriptFile when open. Write to OUTPUT when not open or IsTranscriptMirrored + procedure WriteLine(buf : inout line) ; + procedure Print(s : string) ; + + -- Create "count" number of blank lines + procedure BlankLine (count : integer := 1) ; + +end TranscriptPkg ; + +--- /////////////////////////////////////////////////////////////////////////// +--- /////////////////////////////////////////////////////////////////////////// +--- /////////////////////////////////////////////////////////////////////////// + +package body TranscriptPkg is + ------------------------------------------------------------ + type LocalBooleanPType is protected + procedure Set (A : boolean) ; + impure function get return boolean ; + end protected LocalBooleanPType ; + type LocalBooleanPType is protected body + variable GlobalVar : boolean := FALSE ; + procedure Set (A : boolean) is + begin + GlobalVar := A ; + end procedure Set ; + impure function get return boolean is + begin + return GlobalVar ; + end function get ; + end protected body LocalBooleanPType ; + + ------------------------------------------------------------ + shared variable TranscriptEnable : LocalBooleanPType ; + shared variable TranscriptMirror : LocalBooleanPType ; + + ------------------------------------------------------------ + procedure TranscriptOpen (Status: out FILE_OPEN_STATUS; ExternalName: STRING; OpenKind: WRITE_APPEND_OPEN_KIND := WRITE_MODE) is + ------------------------------------------------------------ + begin + file_open(Status, TranscriptFile, ExternalName, OpenKind) ; + if Status = OPEN_OK then + TranscriptEnable.Set(TRUE) ; + end if ; + end procedure TranscriptOpen ; + + ------------------------------------------------------------ + procedure TranscriptOpen (ExternalName: STRING; OpenKind: WRITE_APPEND_OPEN_KIND := WRITE_MODE) is + ------------------------------------------------------------ + variable Status : FILE_OPEN_STATUS ; + begin + TranscriptOpen(Status, ExternalName, OpenKind) ; + if Status /= OPEN_OK then + report "TranscriptPkg.TranscriptOpen file: " & + ExternalName & " status is: " & to_string(status) & " and is not OPEN_OK" severity FAILURE ; + end if ; + end procedure TranscriptOpen ; + + ------------------------------------------------------------ + impure function TranscriptOpen (ExternalName: STRING; OpenKind: WRITE_APPEND_OPEN_KIND := WRITE_MODE) return FILE_OPEN_STATUS is + ------------------------------------------------------------ + variable Status : FILE_OPEN_STATUS ; + begin + TranscriptOpen(Status, ExternalName, OpenKind) ; + return Status ; + end function TranscriptOpen ; + + ------------------------------------------------------------ + procedure TranscriptClose is + ------------------------------------------------------------ + begin + if TranscriptEnable.Get then + file_close(TranscriptFile) ; + end if ; + TranscriptEnable.Set(FALSE) ; + end procedure TranscriptClose ; + + ------------------------------------------------------------ + impure function IsTranscriptOpen return boolean is + ------------------------------------------------------------ + begin + return TranscriptEnable.Get ; + end function IsTranscriptOpen ; + + ------------------------------------------------------------ + procedure SetTranscriptMirror (A : boolean := TRUE) is + ------------------------------------------------------------ + begin + TranscriptMirror.Set(A) ; + end procedure SetTranscriptMirror ; + + ------------------------------------------------------------ + impure function IsTranscriptMirrored return boolean is + ------------------------------------------------------------ + begin + return TranscriptMirror.Get ; + end function IsTranscriptMirrored ; + + ------------------------------------------------------------ + procedure WriteLine(buf : inout line) is + ------------------------------------------------------------ + begin + if not TranscriptEnable.Get then + WriteLine(OUTPUT, buf) ; + elsif TranscriptMirror.Get then + TEE(TranscriptFile, buf) ; + else + WriteLine(TranscriptFile, buf) ; + end if ; + end procedure WriteLine ; + + ------------------------------------------------------------ + procedure Print(s : string) is + ------------------------------------------------------------ + variable buf : line ; + begin + write(buf, s) ; + WriteLine(buf) ; + end procedure Print ; + + ------------------------------------------------------------ + procedure BlankLine (count : integer := 1) is + ------------------------------------------------------------ + begin + for i in 1 to count loop + print("") ; + end loop ; + end procedure Blankline ; + +end package body TranscriptPkg ; \ No newline at end of file diff --git a/OSVVM/VendorCovApiPkg.vhd b/OSVVM/VendorCovApiPkg.vhd new file mode 100644 index 0000000..56f8c4b --- /dev/null +++ b/OSVVM/VendorCovApiPkg.vhd @@ -0,0 +1,120 @@ +-- +-- File Name: VendorCovApiPkg.vhd +-- Design Unit Name: VendorCovApiPkg +-- Revision: STANDARD VERSION +-- +-- Maintainer: Jim Lewis email: jim@synthworks.com +-- +-- Based on work done in package VendorCovApiPkg_Aldec.vhd by: +-- ... +-- +-- +-- Package Defines +-- A set of foreign procedures that link OSVVM's CoveragePkg +-- coverage model creation and coverage capture with the +-- built-in capability of a simulator. +-- +-- +-- Revision History: For more details, see CoveragePkg_release_notes.pdf +-- Date Version Description +-- 11/2016: 2016.11 Initial revision +-- +-- +-- Copyright (c) 2016 by SynthWorks Design Inc. All rights reserved. +-- +-- Verbatim copies of this source file may be used and +-- distributed without restriction. +-- +-- Modified copies of this source file may be distributed +-- under the terms of the ARTISTIC License as published by +-- The Perl Foundation; either version 2.0 of the License, +-- or (at your option) any later version. +-- +-- This source is distributed in the hope that it will be +-- useful, but WITHOUT ANY WARRANTY; without even the implied +-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +-- PURPOSE. See the Artistic License for details. +-- +-- You should have received a copy of the license with this source. +-- If not download it from, +-- http://www.perlfoundation.org/artistic_license_2_0 +-- -- +-------------------------------------------------------------------------- + +package VendorCovApiPkg is + + subtype VendorCovHandleType is integer; + + -- Types for how coverage bins are represented. Matches OSVVM types. + type VendorCovRangeType is record + min: integer; + max: integer; + end record; + + type VendorCovRangeArrayType is array ( integer range <> ) of VendorCovRangeType; + + -- Create Initial Data Structure for Point/Item Functional Coverage Model + -- Sets initial name of the coverage model if available + impure function VendorCovPointCreate( name: string ) return VendorCovHandleType; + + -- Create Initial Data Structure for Cross Functional Coverage Model + -- Sets initial name of the coverage model if available + impure function VendorCovCrossCreate( name: string ) return VendorCovHandleType; + + -- Sets/Updates the name of the Coverage Model. + -- Should not be called until the data structure is created by VendorCovPointCreate or VendorCovCrossCreate. + -- Replaces name that was set by VendorCovPointCreate or VendorCovCrossCreate. + procedure VendorCovSetName( obj: VendorCovHandleType; name: string ); + + -- Add a bin or set of bins to either a Point/Item or Cross Functional Coverage Model + -- Checking for sizing that is different from original sizing already done in OSVVM CoveragePkg + -- It is important to maintain an index that corresponds to the order the bins were entered as + -- that is used when coverage is recorded. + procedure VendorCovBinAdd( obj: VendorCovHandleType; bins: VendorCovRangeArrayType; Action: integer; atleast: integer; name: string ); + + -- Increment the coverage of bin identified by index number. + -- Index ranges from 1 to Number of Bins. + -- Index corresponds to the order the bins were entered (starting from 1) + procedure VendorCovBinInc( obj: VendorCovHandleType; index: integer ); + + +end package; + +package body VendorCovApiPkg is + -- Create Initial Data Structure for Point/Item Functional Coverage Model + -- Sets initial name of the coverage model if available + impure function VendorCovPointCreate( name: string ) return VendorCovHandleType is + begin + return 0 ; + end function VendorCovPointCreate ; + + -- Create Initial Data Structure for Cross Functional Coverage Model + -- Sets initial name of the coverage model if available + impure function VendorCovCrossCreate( name: string ) return VendorCovHandleType is + begin + return 0 ; + end function VendorCovCrossCreate ; + + -- Sets/Updates the name of the Coverage Model. + -- Should not be called until the data structure is created by VendorCovPointCreate or VendorCovCrossCreate. + -- Replaces name that was set by VendorCovPointCreate or VendorCovCrossCreate. + procedure VendorCovSetName( obj: VendorCovHandleType; name: string ) is + begin + end procedure VendorCovSetName ; + + -- Add a bin or set of bins to either a Point/Item or Cross Functional Coverage Model + -- Checking for sizing that is different from original sizing already done in OSVVM CoveragePkg + -- It is important to maintain an index that corresponds to the order the bins were entered as + -- that is used when coverage is recorded. + procedure VendorCovBinAdd( obj: VendorCovHandleType; bins: VendorCovRangeArrayType; Action: integer; atleast: integer; name: string )is + begin + end procedure VendorCovBinAdd ; + + -- Increment the coverage of bin identified by index number. + -- Index ranges from 1 to Number of Bins. + -- Index corresponds to the order the bins were entered (starting from 1) + procedure VendorCovBinInc( obj: VendorCovHandleType; index: integer )is + begin + end procedure VendorCovBinInc ; + +end package body VendorCovApiPkg ; diff --git a/OSVVM/VendorCovApiPkg_Aldec.vhd b/OSVVM/VendorCovApiPkg_Aldec.vhd new file mode 100644 index 0000000..00d323c --- /dev/null +++ b/OSVVM/VendorCovApiPkg_Aldec.vhd @@ -0,0 +1,92 @@ +-- +-- File Name: VendorCovApiPkg_Aldec.vhd +-- Design Unit Name: VendorCovApiPkg +-- Revision: ALDEC VERSION +-- +-- Maintainer: +-- +-- Package Defines +-- A set of foreign procedures that link OSVVM's CoveragePkg +-- coverage model creation and coverage capture with the +-- built-in capability of a simulator. +-- +-- +-- Revision History: For more details, see CoveragePkg_release_notes.pdf +-- Date Version Description +-- 11/2016: 2016.11 Initial revision +-- 12/2016 2016.11a Fixed an issue with attributes +-- +-- +-- Copyright (c) 2016 by Aldec. All rights reserved. +-- +-- Verbatim copies of this source file may be used and +-- distributed without restriction. +-- +-- Modified copies of this source file may be distributed +-- under the terms of the ARTISTIC License as published by +-- The Perl Foundation; either version 2.0 of the License, +-- or (at your option) any later version. +-- +-- This source is distributed in the hope that it will be +-- useful, but WITHOUT ANY WARRANTY; without even the implied +-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +-- PURPOSE. See the Artistic License for details. +-- +-- You should have received a copy of the license with this source. +-- If not download it from, +-- http://www.perlfoundation.org/artistic_license_2_0 +-- -- +-------------------------------------------------------------------------- + +package VendorCovApiPkg is + + subtype VendorCovHandleType is integer; + + -- Types for how coverage bins are represented. Matches OSVVM types. + type VendorCovRangeType is record + min: integer; + max: integer; + end record; + + type VendorCovRangeArrayType is array ( integer range <> ) of VendorCovRangeType; + + -- Create Initial Data Structure for Point/Item Functional Coverage Model + -- Sets initial name of the coverage model if available + impure function VendorCovPointCreate( name: string ) return VendorCovHandleType; + attribute foreign of VendorCovPointCreate[ string return VendorCovHandleType ]: function is "VHPI systf; cvg_CvpCreate"; + + -- Create Initial Data Structure for Cross Functional Coverage Model + -- Sets initial name of the coverage model if available + impure function VendorCovCrossCreate( name: string ) return VendorCovHandleType; + attribute foreign of VendorCovCrossCreate[ string return VendorCovHandleType ]: function is "VHPI systf; cvg_CrCreate"; + + -- Sets/Updates the name of the Coverage Model. + -- Should not be called until the data structure is created by VendorCovPointCreate or VendorCovCrossCreate. + -- Replaces name that was set by VendorCovPointCreate or VendorCovCrossCreate. + procedure VendorCovSetName( obj: VendorCovHandleType; name: string ); + attribute foreign of VendorCovSetName[ VendorCovHandleType, string ]: procedure is "VHPI systf; cvg_SetCoverName"; + + -- Add a bin or set of bins to either a Point/Item or Cross Functional Coverage Model + -- Checking for sizing that is different from original sizing already done in OSVVM CoveragePkg + -- It is important to maintain an index that corresponds to the order the bins were entered as + -- that is used when coverage is recorded. + procedure VendorCovBinAdd( obj: VendorCovHandleType; bins: VendorCovRangeArrayType; Action: integer; atleast: integer; name: string ); + attribute foreign of VendorCovBinAdd[ VendorCovHandleType, VendorCovRangeArrayType, integer, integer, string ]: procedure is "VHPI systf; cvg_CvpCrBinCreate"; + + -- Increment the coverage of bin identified by index number. + -- Index ranges from 1 to Number of Bins. + -- Index corresponds to the order the bins were entered (starting from 1) + procedure VendorCovBinInc( obj: VendorCovHandleType; index: integer ); + attribute foreign of VendorCovBinInc[ VendorCovHandleType, integer ]: procedure is "VHPI systf; cvg_CvpCrBinIncr"; + + -- Action (integer): + -- constant COV_COUNT : integer := 1; + -- constant COV_IGNORE : integer := 0; + -- constant COV_ILLEGAL : integer := -1; + +end package; + +package body VendorCovApiPkg is + -- Replace any existing package body for this package + +end package body VendorCovApiPkg ; diff --git a/test/Makefile b/test/Makefile index 7912de1..32cb664 100644 --- a/test/Makefile +++ b/test/Makefile @@ -1,6 +1,7 @@ SIM_SRC := ../sim SYN_SRC := ../syn CMN_SRC := ../common +OSVVM_SRC := ../OSVVM VHD08_SRC := vhdl_2008 VHD_STD := 08 @@ -9,11 +10,26 @@ VHD_STD := 08 all: queue dict stack sim wishbone -RandomPkg.o: OSVVM/SortListPkg_int.vhd OSVVM/RandomBasePkg.vhd OSVVM/RandomPkg.vhd - ghdl -a --std=$(VHD_STD) --work=osvvm $^ +OsvvmContext.o: $(OSVVM_SRC)/*.vhd + ghdl -a --std=$(VHD_STD) --work=osvvm $(OSVVM_SRC)/NamePkg.vhd + ghdl -a --std=$(VHD_STD) --work=osvvm $(OSVVM_SRC)/OsvvmGlobalPkg.vhd + ghdl -a --std=$(VHD_STD) --work=osvvm $(OSVVM_SRC)/VendorCovApiPkg.vhd + ghdl -a --std=$(VHD_STD) --work=osvvm $(OSVVM_SRC)/TranscriptPkg.vhd + ghdl -a --std=$(VHD_STD) --work=osvvm $(OSVVM_SRC)/TextUtilPkg.vhd + ghdl -a --std=$(VHD_STD) --work=osvvm $(OSVVM_SRC)/AlertLogPkg.vhd + ghdl -a --std=$(VHD_STD) --work=osvvm $(OSVVM_SRC)/MessagePkg.vhd + ghdl -a --std=$(VHD_STD) --work=osvvm $(OSVVM_SRC)/SortListPkg_int.vhd + ghdl -a --std=$(VHD_STD) --work=osvvm $(OSVVM_SRC)/RandomBasePkg.vhd + ghdl -a --std=$(VHD_STD) --work=osvvm $(OSVVM_SRC)/RandomPkg.vhd + ghdl -a --std=$(VHD_STD) --work=osvvm $(OSVVM_SRC)/CoveragePkg.vhd + ghdl -a --std=$(VHD_STD) --work=osvvm $(OSVVM_SRC)/MemoryPkg.vhd + ghdl -a --std=$(VHD_STD) --work=osvvm $(OSVVM_SRC)/ScoreboardGenericPkg.vhd + ghdl -a --std=$(VHD_STD) --work=osvvm $(OSVVM_SRC)/ScoreboardPkg_slv.vhd + ghdl -a --std=$(VHD_STD) --work=osvvm $(OSVVM_SRC)/ScoreboardPkg_int.vhd + ghdl -a --std=$(VHD_STD) --work=osvvm $(OSVVM_SRC)/ResolutionPkg.vhd + ghdl -a --std=$(VHD_STD) --work=osvvm $(OSVVM_SRC)/TbUtilPkg.vhd + ghdl -a --std=$(VHD_STD) --work=osvvm $(OSVVM_SRC)/OsvvmContext.vhd -CoveragePkg.o: RandomPkg.o OSVVM/MessagePkg.vhd - ghdl -a --std=$(VHD_STD) --work=osvvm OSVVM/MessagePkg.vhd OSVVM/CoveragePkg.vhd UtilsP.o: $(CMN_SRC)/UtilsP.vhd ghdl -a --std=$(VHD_STD) --work=libvhdl $< @@ -24,25 +40,25 @@ UtilsP.o: $(CMN_SRC)/UtilsP.vhd ghdl -a --std=$(VHD_STD) --work=libvhdl $< -queuet: RandomPkg.o AssertP.o QueueP.o QueueT.vhd +queuet: OsvvmContext.o AssertP.o QueueP.o QueueT.vhd ghdl -a --std=$(VHD_STD) QueueT.vhd ghdl -e --std=$(VHD_STD) $@ -dictt: RandomPkg.o DictP.o DictT.vhd +dictt: OsvvmContext.o DictP.o DictT.vhd ghdl -a --std=$(VHD_STD) DictT.vhd ghdl -e --std=$(VHD_STD) $@ -stackt: RandomPkg.o AssertP.o StackP.o StackT.vhd +stackt: OsvvmContext.o AssertP.o StackP.o StackT.vhd ghdl -a --std=$(VHD_STD) StackT.vhd ghdl -e --std=$(VHD_STD) $@ -simt: RandomPkg.o UtilsP.o AssertP.o QueueP.o SimP.o SimT.vhd +simt: OsvvmContext.o UtilsP.o AssertP.o QueueP.o SimP.o SimT.vhd ghdl -a --std=$(VHD_STD) SimT.vhd ghdl -e --std=$(VHD_STD) $@ -spit: RandomPkg.o UtilsP.o $(SYN_SRC)/SpiSlaveE.vhd $(SYN_SRC)/SpiMasterE.vhd SpiT.vhd +spit: OsvvmContext.o UtilsP.o $(SYN_SRC)/SpiSlaveE.vhd $(SYN_SRC)/SpiMasterE.vhd SpiT.vhd ghdl -a --std=$(VHD_STD) -fpsl $(SYN_SRC)/SpiSlaveE.vhd $(SYN_SRC)/SpiMasterE.vhd ghdl -a --std=$(VHD_STD) -fpsl SpiT.vhd ghdl -e --std=$(VHD_STD) $@ @@ -52,7 +68,7 @@ spi: spit ghdl -r --std=$(VHD_STD) $@t --wave=$@t.ghw -wishbonet: RandomPkg.o CoveragePkg.o AssertP.o SimP.o QueueP.o DictP.o UtilsP.o \ +wishbonet: OsvvmContext.o AssertP.o SimP.o QueueP.o DictP.o UtilsP.o \ $(SYN_SRC)/WishBoneMasterE.vhd $(SYN_SRC)/WishBoneSlaveE.vhd WishBoneT.vhd ghdl -a --std=$(VHD_STD) -fpsl $(SYN_SRC)/WishBoneMasterE.vhd $(SYN_SRC)/WishBoneSlaveE.vhd ghdl -a --std=$(VHD_STD) -fpsl WishBoneT.vhd