diff options
author | Tristan Gingold <tgingold@free.fr> | 2017-05-18 08:01:02 +0200 |
---|---|---|
committer | Tristan Gingold <tgingold@free.fr> | 2017-05-18 08:01:02 +0200 |
commit | cff9d9a80bc14e81684fd5e02a361c171737022d (patch) | |
tree | cc40a1f680ae5a8ecd1db3e6f27c6a0cbfb30741 /testsuite/gna/issue317/OSVVM | |
parent | 2e3634206b04775398f712a4da735d70a32020f2 (diff) | |
download | ghdl-cff9d9a80bc14e81684fd5e02a361c171737022d.tar.gz ghdl-cff9d9a80bc14e81684fd5e02a361c171737022d.tar.bz2 ghdl-cff9d9a80bc14e81684fd5e02a361c171737022d.zip |
Add testcase for #317
Diffstat (limited to 'testsuite/gna/issue317/OSVVM')
-rw-r--r-- | testsuite/gna/issue317/OSVVM/AlertLogPkg.vhd | 2732 | ||||
-rw-r--r-- | testsuite/gna/issue317/OSVVM/NamePkg.vhd | 129 | ||||
-rw-r--r-- | testsuite/gna/issue317/OSVVM/OsvvmGlobalPkg.vhd | 350 | ||||
-rw-r--r-- | testsuite/gna/issue317/OSVVM/RandomBasePkg.vhd | 234 | ||||
-rw-r--r-- | testsuite/gna/issue317/OSVVM/RandomPkg.vhd | 1647 | ||||
-rw-r--r-- | testsuite/gna/issue317/OSVVM/ScoreboardGenericPkg.vhd | 1573 | ||||
-rw-r--r-- | testsuite/gna/issue317/OSVVM/SortListPkg_int.vhd | 417 | ||||
-rw-r--r-- | testsuite/gna/issue317/OSVVM/TextUtilPkg.vhd | 407 | ||||
-rw-r--r-- | testsuite/gna/issue317/OSVVM/TranscriptPkg.vhd | 200 |
9 files changed, 7689 insertions, 0 deletions
diff --git a/testsuite/gna/issue317/OSVVM/AlertLogPkg.vhd b/testsuite/gna/issue317/OSVVM/AlertLogPkg.vhd new file mode 100644 index 000000000..0e3e15124 --- /dev/null +++ b/testsuite/gna/issue317/OSVVM/AlertLogPkg.vhd @@ -0,0 +1,2732 @@ +-- +-- 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 +-- +-- 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 ; +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 ; + + -- 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 ; + + ------------------------------------------------------------ + -- 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 ; + + -- 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 ; + + ------------------------------------------------------------ + -- 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( 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 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( 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 ) ; + ------------------------------------------------------------ + -- 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 ; + Message : string ; + LogLevel : LogType := PASSED ; + AlertLevel : AlertType := ERROR + ) ; + procedure AffirmIf(condition : boolean ; Message : string ; LogLevel : LogType := PASSED ; AlertLevel : AlertType := ERROR) ; + + ------------------------------------------------------------ + 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 IncAffirmCheckCount ; + impure function GetAffirmCheckCount 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 ; + + 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 ; + impure function IsLoggingEnabled(AlertLogID : AlertLogIDType ; Level : LogType) return boolean ; -- same as GetLogEnable + impure function IsLoggingEnabled(Level : LogType) return boolean ; + + 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 ; + +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 IncAffirmCheckCount ; + impure function GetAffirmCheckCount 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 IncAffirmCheckCount is + ------------------------------------------------------------ + begin + if GlobalAlertEnabledVar then + AffirmCheckCountVar := AffirmCheckCountVar + 1 ; + end if ; + end procedure IncAffirmCheckCount ; + + ------------------------------------------------------------ + impure function GetAffirmCheckCount return natural is + ------------------------------------------------------------ + begin + return AffirmCheckCountVar ; + end function GetAffirmCheckCount ; + +--?? ------------------------------------------------------------ +--?? 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 ; + + ------------------------------------------------------------ + -- deprecated + procedure AlertIf( condition : boolean ; AlertLogID : AlertLogIDType ; Message : string ; Level : AlertType := ERROR ) is + ------------------------------------------------------------ + begin + AlertIf( AlertLogID, condition, Message, Level) ; + 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 with exit conditions in a loop: exit when alert( 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 ; + + ------------------------------------------------------------ + -- 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 ; + + ------------------------------------------------------------ + 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 ; + + ------------------------------------------------------------ + -- deprecated + procedure AlertIfNot( condition : boolean ; AlertLogID : AlertLogIDType ; Message : string ; Level : AlertType := ERROR ) is + ------------------------------------------------------------ + begin + AlertIfNot( AlertLogID, condition, Message, Level) ; + 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 with exit conditions in a loop: exit when alert( 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 ; + + ------------------------------------------------------------ + -- 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 ; + + ------------------------------------------------------------ + 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 ; + + -- 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 ; + + -- 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 ; + + -- 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 ; + + -- 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 AlertIfDiff (AlertLogID : AlertLogIDType ; Name1, Name2 : string; Message : string := "" ; Level : AlertType := ERROR ) is + -- Open files and call AlertIfDiff[text, ...] + ------------------------------------------------------------ + file FileID1, FileID2 : text ; + variable status1, status2 : file_open_status ; + begin + file_open(status1, FileID1, Name1, READ_MODE) ; + file_open(status2, FileID2, Name2, READ_MODE) ; + if status1 = OPEN_OK and status2 = OPEN_OK then + AlertIfDiff (AlertLogID, FileID1, FileID2, Message & " " & Name1 & " /= " & Name2 & ", ", Level) ; + 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 AlertIfDiff ; + + ------------------------------------------------------------ + procedure AlertIfDiff (Name1, Name2 : string; Message : string := "" ; Level : AlertType := ERROR ) is + ------------------------------------------------------------ + begin + AlertIfDiff (ALERT_DEFAULT_ID, Name1, Name2, Message, Level) ; + end procedure AlertIfDiff ; + + ------------------------------------------------------------ + procedure AlertIfDiff (AlertLogID : AlertLogIDType ; file File1, File2 : text; Message : string := "" ; Level : AlertType := ERROR ) 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; + end procedure AlertIfDiff ; + + ------------------------------------------------------------ + procedure AlertIfDiff (file File1, File2 : text; Message : string := "" ; Level : AlertType := ERROR ) is + ------------------------------------------------------------ + begin + AlertIfDiff (ALERT_DEFAULT_ID, File1, File2, Message, Level) ; + end procedure AlertIfDiff ; + + ------------------------------------------------------------ + procedure AffirmIf( + ------------------------------------------------------------ + AlertLogID : AlertLogIDType ; + condition : boolean ; + Message : string ; + LogLevel : LogType := PASSED ; + AlertLevel : AlertType := ERROR + ) is + begin + AlertLogStruct.IncAffirmCheckCount ; -- 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 ; + + ------------------------------------------------------------ + procedure AffirmIf(condition : boolean ; Message : string ; LogLevel : LogType := PASSED ; AlertLevel : AlertType := ERROR) is + ------------------------------------------------------------ + begin + AffirmIf(ALERT_DEFAULT_ID, condition, Message, LogLevel, AlertLevel) ; + end procedure AffirmIf; + + ------------------------------------------------------------ + 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 IncAffirmCheckCount is + ------------------------------------------------------------ + begin + AlertLogStruct.IncAffirmCheckCount ; + end procedure IncAffirmCheckCount ; + + ------------------------------------------------------------ + impure function GetAffirmCheckCount return natural is + ------------------------------------------------------------ + begin + return AlertLogStruct.GetAffirmCheckCount ; + end function GetAffirmCheckCount ; + +--?? ------------------------------------------------------------ +--?? 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 ; + + ------------------------------------------------------------ + impure function IsLoggingEnabled(AlertLogID : AlertLogIDType ; Level : LogType) return boolean is + ------------------------------------------------------------ + begin + return AlertLogStruct.GetLogEnable(AlertLogID, Level) ; + end function IsLoggingEnabled ; + + ------------------------------------------------------------ + impure function IsLoggingEnabled(Level : LogType) return boolean is + ------------------------------------------------------------ + begin + return AlertLogStruct.GetLogEnable(LOG_DEFAULT_ID, Level) ; + end function IsLoggingEnabled ; + + ------------------------------------------------------------ + 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 ; + +end package body AlertLogPkg ;
\ No newline at end of file diff --git a/testsuite/gna/issue317/OSVVM/NamePkg.vhd b/testsuite/gna/issue317/OSVVM/NamePkg.vhd new file mode 100644 index 000000000..44e4ec6cf --- /dev/null +++ b/testsuite/gna/issue317/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/testsuite/gna/issue317/OSVVM/OsvvmGlobalPkg.vhd b/testsuite/gna/issue317/OSVVM/OsvvmGlobalPkg.vhd new file mode 100644 index 000000000..1d61e2bd3 --- /dev/null +++ b/testsuite/gna/issue317/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/testsuite/gna/issue317/OSVVM/RandomBasePkg.vhd b/testsuite/gna/issue317/OSVVM/RandomBasePkg.vhd new file mode 100644 index 000000000..9dc00d8e2 --- /dev/null +++ b/testsuite/gna/issue317/OSVVM/RandomBasePkg.vhd @@ -0,0 +1,234 @@ +-- +-- File Name: RandomBasePkg.vhd +-- Design Unit Name: RandomBasePkg +-- Revision: STANDARD VERSION +-- +-- Maintainer: Jim Lewis email: jim@synthworks.com +-- Contributor(s): +-- Jim Lewis jim@synthworks.com +-- +-- +-- Description: +-- Defines Base randomization, seed definition, seed generation, +-- and seed IO functionality for RandomPkg.vhd +-- Defines: +-- Procedure Uniform - baseline randomization +-- Type RandomSeedType - the seed as a single object +-- function GenRandSeed from integer_vector, integer, or string +-- IO function to_string, & procedures write, read +-- +-- In revision 2.0 these types and functions are included by package reference. +-- Long term these will be passed as generics to RandomGenericPkg +-- +-- +-- 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/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 ; +-- 03/01/2011 2.0 STANDARD VERSION +-- 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 - 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 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 + + +package RandomBasePkg is + + -- RandomSeedType and Uniform can be replaced by any procedure that + -- produces a uniform distribution with 0 <= Value < 1 or 0 < Value < 1 + -- and maintains the same call interface + type RandomSeedType is array (1 to 2) of integer ; + procedure Uniform (Result : out real ; Seed : inout RandomSeedType) ; + + -- Translate from integer_vector, integer, or string to RandomSeedType + -- Required by RandomPkg.InitSeed + -- GenRandSeed makes sure all values are in a valid range + 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. + -- Not required by RandomPkg + function to_string(A : RandomSeedType) return string ; + procedure write(variable L: inout line ; A : RandomSeedType ) ; + procedure read (variable L: inout line ; A : out RandomSeedType ; good : out boolean ) ; + procedure read (variable L: inout line ; A : out RandomSeedType ) ; + +end RandomBasePkg ; + +--- /////////////////////////////////////////////////////////////////////////// +--- /////////////////////////////////////////////////////////////////////////// +--- /////////////////////////////////////////////////////////////////////////// + +package body RandomBasePkg is + + ----------------------------------------------------------------- + -- Uniform + -- Generate a random number with a Uniform distribution + -- Required by RandomPkg. All randomization is derived from here. + -- Value produced must be either: + -- 0 <= Value < 1 or 0 < Value < 1 + -- + -- Current version uses ieee.math_real.Uniform + -- This abstraction allows higher precision version + -- of a uniform distribution to be used provided + -- + procedure Uniform ( + Result : out real ; + Seed : inout RandomSeedType + ) is + begin + ieee.math_real.Uniform (Seed(Seed'left), Seed(Seed'right), Result) ; + end procedure Uniform ; + + + ----------------------------------------------------------------- + -- GenRandSeed + -- Convert integer_vector to RandomSeedType + -- Uniform requires two seed values of the form: + -- 1 <= SEED1 <= 2147483562; 1 <= SEED2 <= 2147483398 + -- + -- if 2 seed values are passed to GenRandSeed and they are + -- in the above range, then they must remain unmodified. + -- + 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 ; + constant SEED1_MAX : integer := 2147483562 ; + constant SEED2_MAX : integer := 2147483398 ; + begin + if iIV'Length <= 0 then -- no seed + 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 + -- inefficient handling, but condition is unlikely + return GenRandSeed(iIV(1)) ; -- generate a seed + + else -- only use the left two values + -- 1 <= SEED1 <= 2147483562 + -- mod returns 0 to MAX-1, the -1 adjusts legal values, +1 adjusts them back + Seed1 := ((iIV(1)-1) mod SEED1_MAX) + 1 ; + -- 1 <= SEED2 <= 2147483398 + Seed2 := ((iIV(2)-1) mod SEED2_MAX) + 1 ; + return (Seed1, Seed2) ; + end if ; + end function GenRandSeed ; + + + ----------------------------------------------------------------- + -- GenRandSeed + -- transform a single integer into the internal seed + -- + impure function GenRandSeed(I : integer) return RandomSeedType is + variable result : integer_vector(1 to 2) ; + begin + result(1) := I ; + result(2) := I/3 + 1 ; + return GenRandSeed(result) ; -- make value ranges legal + end function GenRandSeed ; + + + ----------------------------------------------------------------- + -- GenRandSeed + -- transform a string value into the internal seed + -- usage: RV.GenRandSeed(RV'instance_path)); + -- + 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 ; + variable result : integer_vector(1 to 2) ; + variable temp : integer := 0 ; + begin + for i in 1 to HALF_LEN loop + temp := (temp + character'pos(revS(i))) mod (integer'right - 2**8) ; + end loop ; + result(1) := temp ; + for i in HALF_LEN + 1 to LEN loop + temp := (temp + character'pos(revS(i))) mod (integer'right - 2**8) ; + end loop ; + result(2) := temp ; + return GenRandSeed(result) ; -- make value ranges legal + end function GenRandSeed ; + + + ----------------------------------------------------------------- + function to_string(A : RandomSeedType) return string is + begin + return to_string(A(A'left)) & " " & to_string(A(A'right)) ; + end function to_string ; + + + ----------------------------------------------------------------- + procedure write(variable L: inout line ; A : RandomSeedType ) is + begin + write(L, to_string(A)) ; + end procedure ; + + + ----------------------------------------------------------------- + procedure read(variable L: inout line ; A : out RandomSeedType ; good : out boolean ) is + variable iReadValid : boolean ; + begin + for i in A'range loop + read(L, A(i), iReadValid) ; + exit when not iReadValid ; + end loop ; + good := iReadValid ; + end procedure read ; + + + ----------------------------------------------------------------- + procedure read(variable L: inout line ; A : out RandomSeedType ) is + variable ReadValid : boolean ; + begin + 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/testsuite/gna/issue317/OSVVM/RandomPkg.vhd b/testsuite/gna/issue317/OSVVM/RandomPkg.vhd new file mode 100644 index 000000000..8c5065881 --- /dev/null +++ b/testsuite/gna/issue317/OSVVM/RandomPkg.vhd @@ -0,0 +1,1647 @@ +-- +-- 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/testsuite/gna/issue317/OSVVM/ScoreboardGenericPkg.vhd b/testsuite/gna/issue317/OSVVM/ScoreboardGenericPkg.vhd new file mode 100644 index 000000000..17a227fa1 --- /dev/null +++ b/testsuite/gna/issue317/OSVVM/ScoreboardGenericPkg.vhd @@ -0,0 +1,1573 @@ +-- +-- 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 +-- +-- +-- +-- 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 (BFM or 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 ; + + IncAffirmCheckCount ; + +-- 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, " Expected: " & expected_to_string(ExpectedPtr.all)) ; + write(WriteBuf, " Actual: " & actual_to_string(ActualData)) ; + 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/testsuite/gna/issue317/OSVVM/SortListPkg_int.vhd b/testsuite/gna/issue317/OSVVM/SortListPkg_int.vhd new file mode 100644 index 000000000..6f32151c5 --- /dev/null +++ b/testsuite/gna/issue317/OSVVM/SortListPkg_int.vhd @@ -0,0 +1,417 @@ +-- +-- 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/testsuite/gna/issue317/OSVVM/TextUtilPkg.vhd b/testsuite/gna/issue317/OSVVM/TextUtilPkg.vhd new file mode 100644 index 000000000..d1c5ee17e --- /dev/null +++ b/testsuite/gna/issue317/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/testsuite/gna/issue317/OSVVM/TranscriptPkg.vhd b/testsuite/gna/issue317/OSVVM/TranscriptPkg.vhd new file mode 100644 index 000000000..a88b00a25 --- /dev/null +++ b/testsuite/gna/issue317/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 |