@ -0,0 +1,672 @@ | |||
-- | |||
-- File Name: MemoryPkg.vhd | |||
-- Design Unit Name: MemoryPkg | |||
-- Revision: STANDARD VERSION | |||
-- | |||
-- Maintainer: Jim Lewis email: jim@synthworks.com | |||
-- Contributor(s): | |||
-- Jim Lewis email: jim@synthworks.com | |||
-- | |||
-- Description | |||
-- Package defines a protected type, MemoryPType, and methods | |||
-- for efficiently implementing memory data structures | |||
-- | |||
-- Developed for: | |||
-- SynthWorks Design Inc. | |||
-- VHDL Training Classes | |||
-- 11898 SW 128th Ave. Tigard, Or 97223 | |||
-- http://www.SynthWorks.com | |||
-- | |||
-- Revision History: | |||
-- Date Version Description | |||
-- 05/2005: 0.1 Initial revision | |||
-- 06/2015: 2015.06 Updated for Alerts, ... | |||
-- Numerous revisions for VHDL Testbenches and Verification | |||
-- 01/2016: 2016.01 Update for buf.all(buf'left) | |||
-- 11/2016: 2016.11 Refinement to MemRead to return value, X (if X), U (if not initialized) | |||
-- | |||
-- | |||
-- Copyright (c) 2005 - 2016 by SynthWorks Design Inc. All rights reserved. | |||
-- | |||
-- Verbatim copies of this source file may be used and | |||
-- distributed without restriction. | |||
-- | |||
-- This source file is free software; you can redistribute it | |||
-- and/or modify it under the terms of the ARTISTIC License | |||
-- as published by The Perl Foundation; either version 2.0 of | |||
-- the License, or (at your option) any later version. | |||
-- | |||
-- This source is distributed in the hope that it will be | |||
-- useful, but WITHOUT ANY WARRANTY; without even the implied | |||
-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR | |||
-- PURPOSE. See the Artistic License for details. | |||
-- | |||
-- You should have received a copy of the license with this source. | |||
-- If not download it from, | |||
-- http://www.perlfoundation.org/artistic_license_2_0 | |||
-- | |||
use std.textio.all ; | |||
library IEEE ; | |||
use IEEE.std_logic_1164.all ; | |||
use IEEE.numeric_std.all ; | |||
use IEEE.numeric_std_unsigned.all ; | |||
use IEEE.math_real.all ; | |||
use work.TextUtilPkg.all ; | |||
use work.TranscriptPkg.all ; | |||
use work.AlertLogPkg.all ; | |||
package MemoryPkg is | |||
type MemoryPType is protected | |||
------------------------------------------------------------ | |||
procedure MemInit ( AddrWidth, DataWidth : in integer ) ; | |||
------------------------------------------------------------ | |||
procedure MemWrite ( Addr, Data : in std_logic_vector ) ; | |||
------------------------------------------------------------ | |||
procedure MemRead ( | |||
Addr : in std_logic_vector ; | |||
Data : out std_logic_vector | |||
) ; | |||
impure function MemRead ( Addr : std_logic_vector ) return std_logic_vector ; | |||
------------------------------------------------------------ | |||
procedure MemErase ; | |||
procedure deallocate ; | |||
------------------------------------------------------------ | |||
procedure SetAlertLogID (A : AlertLogIDType) ; | |||
procedure SetAlertLogID (Name : string ; ParentID : AlertLogIDType := ALERTLOG_BASE_ID ; CreateHierarchy : Boolean := TRUE) ; | |||
impure function GetAlertLogID return AlertLogIDType ; | |||
------------------------------------------------------------ | |||
procedure FileReadH ( -- Hexadecimal File Read | |||
FileName : string ; | |||
StartAddr : std_logic_vector ; | |||
EndAddr : std_logic_vector | |||
) ; | |||
procedure FileReadH (FileName : string ; StartAddr : std_logic_vector) ; | |||
procedure FileReadH (FileName : string) ; | |||
------------------------------------------------------------ | |||
procedure FileReadB ( -- Binary File Read | |||
FileName : string ; | |||
StartAddr : std_logic_vector ; | |||
EndAddr : std_logic_vector | |||
) ; | |||
procedure FileReadB (FileName : string ; StartAddr : std_logic_vector) ; | |||
procedure FileReadB (FileName : string) ; | |||
------------------------------------------------------------ | |||
procedure FileWriteH ( -- Hexadecimal File Write | |||
FileName : string ; | |||
StartAddr : std_logic_vector ; | |||
EndAddr : std_logic_vector | |||
) ; | |||
procedure FileWriteH (FileName : string ; StartAddr : std_logic_vector) ; | |||
procedure FileWriteH (FileName : string) ; | |||
------------------------------------------------------------ | |||
procedure FileWriteB ( -- Binary File Write | |||
FileName : string ; | |||
StartAddr : std_logic_vector ; | |||
EndAddr : std_logic_vector | |||
) ; | |||
procedure FileWriteB (FileName : string ; StartAddr : std_logic_vector) ; | |||
procedure FileWriteB (FileName : string) ; | |||
end protected MemoryPType ; | |||
end MemoryPkg ; | |||
package body MemoryPkg is | |||
constant BLOCK_WIDTH : integer := 10 ; | |||
type MemoryPType is protected body | |||
type MemBlockType is array (integer range <>) of integer ; | |||
type MemBlockPtrType is access MemBlockType ; | |||
type MemArrayType is array (integer range <>) of MemBlockPtrType ; | |||
type ArrayPtrVarType is access MemArrayType ; | |||
variable ArrayPtrVar : ArrayPtrVarType := NULL ; | |||
variable AddrWidthVar : integer := -1 ; -- set by MemInit - merges addr length and initialized checks. | |||
variable DataWidthVar : natural := 1 ; -- set by MemInit | |||
variable BlockkWidthVar : natural := 0 ; -- set by MemInit | |||
variable AlertLogIDVar : AlertLogIDType := OSVVM_ALERTLOG_ID ; | |||
type FileFormatType is (BINARY, HEX) ; | |||
------------------------------------------------------------ | |||
procedure MemInit ( AddrWidth, DataWidth : In integer ) is | |||
------------------------------------------------------------ | |||
begin | |||
if AddrWidth <= 0 then | |||
Alert(AlertLogIDVar, "MemoryPType.MemInit. AddrWidth = " & to_string(AddrWidth) & " must be > 0.", FAILURE) ; | |||
return ; | |||
end if ; | |||
if DataWidth <= 0 then | |||
Alert(AlertLogIDVar, "MemoryPType.MemInit. DataWidth = " & to_string(DataWidth) & " must be > 0.", FAILURE) ; | |||
return ; | |||
end if ; | |||
AddrWidthVar := AddrWidth ; | |||
DataWidthVar := DataWidth ; | |||
BlockkWidthVar := minimum(BLOCK_WIDTH, AddrWidth) ; | |||
ArrayPtrVar := new MemArrayType(0 to 2**(AddrWidth-BlockkWidthVar)-1) ; | |||
end procedure MemInit ; | |||
------------------------------------------------------------ | |||
procedure MemWrite ( Addr, Data : in std_logic_vector ) is | |||
------------------------------------------------------------ | |||
variable BlockAddr, WordAddr : integer ; | |||
alias aAddr : std_logic_vector (Addr'length-1 downto 0) is Addr ; | |||
begin | |||
-- Check Bounds of Address and if memory is initialized | |||
if Addr'length /= AddrWidthVar then | |||
if (ArrayPtrVar = NULL) then | |||
Alert(AlertLogIDVar, "MemoryPType.MemWrite: Memory not initialized, Write Ignored.", FAILURE) ; | |||
else | |||
Alert(AlertLogIDVar, "MemoryPType.MemWrite: Addr'length: " & to_string(Addr'length) & " /= Memory Address Width: " & to_string(AddrWidthVar), FAILURE) ; | |||
end if ; | |||
return ; | |||
end if ; | |||
-- Check Bounds on Data | |||
if Data'length /= DataWidthVar then | |||
Alert(AlertLogIDVar, "MemoryPType.MemWrite: Data'length: " & to_string(Data'length) & " /= Memory Data Width: " & to_string(DataWidthVar), FAILURE) ; | |||
return ; | |||
end if ; | |||
if is_X( Addr ) then | |||
Alert(AlertLogIDVar, "MemoryPType.MemWrite: Address X, Write Ignored.") ; | |||
return ; | |||
end if ; | |||
-- Slice out upper address to form block address | |||
if aAddr'high >= BlockkWidthVar then | |||
BlockAddr := to_integer(aAddr(aAddr'high downto BlockkWidthVar)) ; | |||
else | |||
BlockAddr := 0 ; | |||
end if ; | |||
-- If empty, allocate a memory block | |||
if (ArrayPtrVar(BlockAddr) = NULL) then | |||
ArrayPtrVar(BlockAddr) := new MemBlockType(0 to 2**BlockkWidthVar-1) ; | |||
end if ; | |||
-- Address of a word within a block | |||
WordAddr := to_integer(aAddr(BlockkWidthVar -1 downto 0)) ; | |||
-- Write to BlockAddr, WordAddr | |||
if (Is_X(Data)) then | |||
ArrayPtrVar(BlockAddr)(WordAddr) := -1 ; | |||
else | |||
ArrayPtrVar(BlockAddr)(WordAddr) := to_integer( Data ) ; | |||
end if ; | |||
end procedure MemWrite ; | |||
------------------------------------------------------------ | |||
procedure MemRead ( | |||
------------------------------------------------------------ | |||
Addr : In std_logic_vector ; | |||
Data : Out std_logic_vector | |||
) is | |||
variable BlockAddr, WordAddr : integer ; | |||
alias aAddr : std_logic_vector (Addr'length-1 downto 0) is Addr ; | |||
begin | |||
-- Check Bounds of Address and if memory is initialized | |||
if Addr'length /= AddrWidthVar then | |||
if (ArrayPtrVar = NULL) then | |||
Alert(AlertLogIDVar, "MemoryPType.MemRead: Memory not initialized. Returning U", FAILURE) ; | |||
else | |||
Alert(AlertLogIDVar, "MemoryPType.MemRead: Addr'length: " & to_string(Addr'length) & " /= Memory Address Width: " & to_string(AddrWidthVar), FAILURE) ; | |||
end if ; | |||
Data := (Data'range => 'U') ; | |||
return ; | |||
end if ; | |||
-- Check Bounds on Data | |||
if Data'length /= DataWidthVar then | |||
Alert(AlertLogIDVar, "MemoryPType.MemRead: Data'length: " & to_string(Data'length) & " /= Memory Data Width: " & to_string(DataWidthVar), FAILURE) ; | |||
Data := (Data'range => 'U') ; | |||
return ; | |||
end if ; | |||
-- If Addr X, data = X | |||
if is_X( aAddr ) then | |||
Data := (Data'range => 'X') ; | |||
return ; | |||
end if ; | |||
-- Slice out upper address to form block address | |||
if aAddr'high >= BlockkWidthVar then | |||
BlockAddr := to_integer(aAddr(aAddr'high downto BlockkWidthVar)) ; | |||
else | |||
BlockAddr := 0 ; | |||
end if ; | |||
-- Empty Block, return all U | |||
if (ArrayPtrVar(BlockAddr) = NULL) then | |||
Data := (Data'range => 'U') ; | |||
return ; | |||
end if ; | |||
-- Address of a word within a block | |||
WordAddr := to_integer(aAddr(BlockkWidthVar -1 downto 0)) ; | |||
if ArrayPtrVar(BlockAddr)(WordAddr) >= 0 then | |||
-- Get the Word from the Array | |||
Data := to_slv(ArrayPtrVar(BlockAddr)(WordAddr), Data'length) ; | |||
elsif ArrayPtrVar(BlockAddr)(WordAddr) = -1 then | |||
-- X in Word, return all X | |||
Data := (Data'range => 'X') ; | |||
else | |||
-- Location Uninitialized, return all X | |||
Data := (Data'range => 'U') ; | |||
end if ; | |||
end procedure MemRead ; | |||
------------------------------------------------------------ | |||
impure function MemRead ( Addr : std_logic_vector ) return std_logic_vector is | |||
------------------------------------------------------------ | |||
variable BlockAddr, WordAddr : integer ; | |||
alias aAddr : std_logic_vector (Addr'length-1 downto 0) is Addr ; | |||
variable Data : std_logic_vector(DataWidthVar-1 downto 0) ; | |||
begin | |||
MemRead(Addr, Data) ; | |||
return Data ; | |||
end function MemRead ; | |||
------------------------------------------------------------ | |||
procedure MemErase is | |||
-- Deallocate the memory, but not the array of pointers | |||
------------------------------------------------------------ | |||
begin | |||
for BlockAddr in ArrayPtrVar'range loop | |||
if (ArrayPtrVar(BlockAddr) /= NULL) then | |||
deallocate (ArrayPtrVar(BlockAddr)) ; | |||
end if ; | |||
end loop ; | |||
end procedure ; | |||
------------------------------------------------------------ | |||
procedure deallocate is | |||
-- Deallocate all allocated memory | |||
------------------------------------------------------------ | |||
begin | |||
MemErase ; | |||
deallocate(ArrayPtrVar) ; | |||
AddrWidthVar := -1 ; | |||
DataWidthVar := 1 ; | |||
BlockkWidthVar := 0 ; | |||
end procedure ; | |||
------------------------------------------------------------ | |||
procedure SetAlertLogID (A : AlertLogIDType) is | |||
------------------------------------------------------------ | |||
begin | |||
AlertLogIDVar := A ; | |||
end procedure SetAlertLogID ; | |||
------------------------------------------------------------ | |||
procedure SetAlertLogID(Name : string ; ParentID : AlertLogIDType := ALERTLOG_BASE_ID ; CreateHierarchy : Boolean := TRUE) is | |||
------------------------------------------------------------ | |||
begin | |||
AlertLogIDVar := GetAlertLogID(Name, ParentID, CreateHierarchy) ; | |||
end procedure SetAlertLogID ; | |||
------------------------------------------------------------ | |||
impure function GetAlertLogID return AlertLogIDType is | |||
------------------------------------------------------------ | |||
begin | |||
return AlertLogIDVar ; | |||
end function GetAlertLogID ; | |||
------------------------------------------------------------ | |||
-- PT Local | |||
procedure FileReadX ( | |||
-- Hexadecimal or Binary File Read | |||
------------------------------------------------------------ | |||
FileName : string ; | |||
DataFormat : FileFormatType ; | |||
StartAddr : std_logic_vector ; | |||
EndAddr : std_logic_vector | |||
) is | |||
-- Format: | |||
-- @hh..h -- Address in hex | |||
-- hhh_XX_ZZ -- data values in hex - space delimited | |||
-- "--" or "//" -- comments | |||
file MemFile : text open READ_MODE is FileName ; | |||
variable Addr : std_logic_vector(AddrWidthVar - 1 downto 0) ; | |||
variable SmallAddr : std_logic_vector(AddrWidthVar - 1 downto 0) ; | |||
variable BigAddr : std_logic_vector(AddrWidthVar - 1 downto 0) ; | |||
variable Data : std_logic_vector(DataWidthVar - 1 downto 0) ; | |||
variable LineNum : natural ; | |||
variable ItemNum : natural ; | |||
variable AddrInc : std_logic_vector(AddrWidthVar - 1 downto 0) ; | |||
variable buf : line ; | |||
variable ReadValid : boolean ; | |||
variable Empty : boolean ; | |||
variable MultiLineComment : boolean ; | |||
variable NextChar : character ; | |||
variable StrLen : integer ; | |||
begin | |||
MultiLineComment := FALSE ; | |||
if StartAddr'length /= AddrWidthVar and EndAddr'length /= AddrWidthVar then | |||
if (ArrayPtrVar = NULL) then | |||
Alert(AlertLogIDVar, "MemoryPType.FileReadX: Memory not initialized, FileRead Ignored.", FAILURE) ; | |||
else | |||
Alert(AlertLogIDVar, "MemoryPType.FileReadX: Addr'length: " & to_string(Addr'length) & " /= Memory Address Width: " & to_string(AddrWidthVar), FAILURE) ; | |||
end if ; | |||
return ; | |||
end if ; | |||
Addr := StartAddr ; | |||
LineNum := 0 ; | |||
if StartAddr <= EndAddr then | |||
SmallAddr := StartAddr ; | |||
BigAddr := EndAddr ; | |||
AddrInc := (AddrWidthVar -1 downto 0 => '0') + 1 ; | |||
else | |||
SmallAddr := EndAddr ; | |||
BigAddr := StartAddr ; | |||
AddrInc := (others => '1') ; -- -1 | |||
end if; | |||
ReadLineLoop : while not EndFile(MemFile) loop | |||
ReadLine(MemFile, buf) ; | |||
LineNum := LineNum + 1 ; | |||
ItemNum := 0 ; | |||
ItemLoop : loop | |||
EmptyOrCommentLine(buf, Empty, MultiLineComment) ; | |||
exit ItemLoop when Empty ; | |||
ItemNum := ItemNum + 1 ; | |||
NextChar := buf.all(buf'left) ; | |||
if (NextChar = '@') then | |||
-- Get Address | |||
read(buf, NextChar) ; | |||
ReadHexToken(buf, Addr, StrLen) ; | |||
exit ReadLineLoop when AlertIf(AlertLogIDVar, StrLen = 0, "MemoryPType.FileReadX: Address length 0 on line: " & to_string(LineNum), FAILURE) ; | |||
exit ItemLoop when AlertIf(AlertLogIDVar, Addr < SmallAddr, | |||
"MemoryPType.FileReadX: Address in file: " & to_hstring(Addr) & | |||
" < StartAddr: " & to_hstring(StartAddr) & " on line: " & to_string(LineNum)) ; | |||
exit ItemLoop when AlertIf(AlertLogIDVar, Addr > BigAddr, | |||
"MemoryPType.FileReadX: Address in file: " & to_hstring(Addr) & | |||
" > EndAddr: " & to_hstring(BigAddr) & " on line: " & to_string(LineNum)) ; | |||
elsif DataFormat = HEX and ishex(NextChar) then | |||
-- Get Hex Data | |||
ReadHexToken(buf, data, StrLen) ; | |||
exit ReadLineLoop when AlertIfNot(AlertLogIDVar, StrLen > 0, | |||
"MemoryPType.FileReadH: Error while reading data on line: " & to_string(LineNum) & | |||
" Item number: " & to_string(ItemNum), FAILURE) ; | |||
log("MemoryPType.FileReadX: MemWrite(Addr => " & to_hstring(Addr) & ", Data => " & to_hstring(Data) & ")", DEBUG) ; | |||
MemWrite(Addr, data) ; | |||
Addr := Addr + AddrInc ; | |||
elsif DataFormat = BINARY and isstd_logic(NextChar) then | |||
-- Get Binary Data | |||
-- read(buf, data, ReadValid) ; | |||
ReadBinaryToken(buf, data, StrLen) ; | |||
-- exit ReadLineLoop when AlertIfNot(AlertLogIDVar, ReadValid, | |||
exit ReadLineLoop when AlertIfNot(AlertLogIDVar, StrLen > 0, | |||
"MemoryPType.FileReadB: Error while reading data on line: " & to_string(LineNum) & | |||
" Item number: " & to_string(ItemNum), FAILURE) ; | |||
log("MemoryPType.FileReadX: MemWrite(Addr => " & to_hstring(Addr) & ", Data => " & to_string(Data) & ")", DEBUG) ; | |||
MemWrite(Addr, data) ; | |||
Addr := Addr + AddrInc ; | |||
else | |||
-- Invalid Text, Issue Warning and skip it | |||
Alert(AlertLogIDVar, | |||
"MemoryPType.FileReadX: Invalid text on line: " & to_string(LineNum) & | |||
" Item: " & to_string(ItemNum) & ". Skipping text: " & buf.all) ; | |||
exit ItemLoop ; | |||
end if ; | |||
end loop ItemLoop ; | |||
end loop ReadLineLoop ; | |||
-- -- must read EndAddr-StartAddr number of words if both start and end specified | |||
-- if (StartAddr /= 0 or (not EndAddr) /= 0) and (Addr /= EndAddr) then | |||
-- Alert("MemoryPType.FileReadH: insufficient data values", WARNING) ; | |||
-- end if ; | |||
file_close(MemFile) ; | |||
end FileReadX ; | |||
------------------------------------------------------------ | |||
procedure FileReadH ( | |||
-- Hexadecimal File Read | |||
------------------------------------------------------------ | |||
FileName : string ; | |||
StartAddr : std_logic_vector ; | |||
EndAddr : std_logic_vector | |||
) is | |||
begin | |||
FileReadX(FileName, HEX, StartAddr, EndAddr) ; | |||
end FileReadH ; | |||
------------------------------------------------------------ | |||
procedure FileReadH (FileName : string ; StartAddr : std_logic_vector) is | |||
-- Hexadecimal File Read | |||
------------------------------------------------------------ | |||
constant EndAddr : std_logic_vector(AddrWidthVar - 1 downto 0) := (others => '1') ; | |||
begin | |||
FileReadX(FileName, HEX, StartAddr, EndAddr) ; | |||
end FileReadH ; | |||
------------------------------------------------------------ | |||
procedure FileReadH (FileName : string) is | |||
-- Hexadecimal File Read | |||
------------------------------------------------------------ | |||
constant StartAddr : std_logic_vector(AddrWidthVar - 1 downto 0) := (others => '0') ; | |||
constant EndAddr : std_logic_vector(AddrWidthVar - 1 downto 0) := (others => '1') ; | |||
begin | |||
FileReadX(FileName, HEX, StartAddr, EndAddr) ; | |||
end FileReadH ; | |||
------------------------------------------------------------ | |||
procedure FileReadB ( | |||
-- Binary File Read | |||
------------------------------------------------------------ | |||
FileName : string ; | |||
StartAddr : std_logic_vector ; | |||
EndAddr : std_logic_vector | |||
) is | |||
begin | |||
FileReadX(FileName, BINARY, StartAddr, EndAddr) ; | |||
end FileReadB ; | |||
------------------------------------------------------------ | |||
procedure FileReadB (FileName : string ; StartAddr : std_logic_vector) is | |||
-- Binary File Read | |||
------------------------------------------------------------ | |||
constant EndAddr : std_logic_vector(AddrWidthVar - 1 downto 0) := (others => '1') ; | |||
begin | |||
FileReadX(FileName, BINARY, StartAddr, EndAddr) ; | |||
end FileReadB ; | |||
------------------------------------------------------------ | |||
procedure FileReadB (FileName : string) is | |||
-- Binary File Read | |||
------------------------------------------------------------ | |||
constant StartAddr : std_logic_vector(AddrWidthVar - 1 downto 0) := (others => '0') ; | |||
constant EndAddr : std_logic_vector(AddrWidthVar - 1 downto 0) := (others => '1') ; | |||
begin | |||
FileReadX(FileName, BINARY, StartAddr, EndAddr) ; | |||
end FileReadB ; | |||
------------------------------------------------------------ | |||
-- PT Local | |||
procedure FileWriteX ( | |||
-- Hexadecimal or Binary File Write | |||
------------------------------------------------------------ | |||
FileName : string ; | |||
DataFormat : FileFormatType ; | |||
StartAddr : std_logic_vector ; | |||
EndAddr : std_logic_vector | |||
) is | |||
-- Format: | |||
-- @hh..h -- Address in hex | |||
-- hhhhh -- data one per line in either hex or binary as specified | |||
file MemFile : text open WRITE_MODE is FileName ; | |||
alias normStartAddr : std_logic_vector(StartAddr'length-1 downto 0) is StartAddr ; | |||
alias normEndAddr : std_logic_vector(EndAddr'length-1 downto 0) is EndAddr ; | |||
variable StartBlockAddr : natural ; | |||
variable EndBlockAddr : natural ; | |||
variable StartWordAddr : natural ; | |||
variable EndWordAddr : natural ; | |||
variable Data : std_logic_vector(DataWidthVar - 1 downto 0) ; | |||
variable FoundData : boolean ; | |||
variable buf : line ; | |||
begin | |||
if StartAddr'length /= AddrWidthVar and EndAddr'length /= AddrWidthVar then | |||
-- Check StartAddr and EndAddr Widths and Memory not initialized | |||
if (ArrayPtrVar = NULL) then | |||
Alert(AlertLogIDVar, "MemoryPType.FileWriteX: Memory not initialized, FileRead Ignored.", FAILURE) ; | |||
else | |||
AlertIf(AlertLogIDVar, StartAddr'length /= AddrWidthVar, "MemoryPType.FileWriteX: StartAddr'length: " | |||
& to_string(StartAddr'length) & | |||
" /= Memory Address Width: " & to_string(AddrWidthVar), FAILURE) ; | |||
AlertIf(AlertLogIDVar, EndAddr'length /= AddrWidthVar, "MemoryPType.FileWriteX: EndAddr'length: " | |||
& to_string(EndAddr'length) & | |||
" /= Memory Address Width: " & to_string(AddrWidthVar), FAILURE) ; | |||
end if ; | |||
return ; | |||
end if ; | |||
if StartAddr > EndAddr then | |||
-- Only support ascending addresses | |||
Alert(AlertLogIDVar, "MemoryPType.FileWriteX: StartAddr: " & to_hstring(StartAddr) & | |||
" > EndAddr: " & to_hstring(EndAddr), FAILURE) ; | |||
return ; | |||
end if ; | |||
-- Slice out upper address to form block address | |||
if AddrWidthVar >= BlockkWidthVar then | |||
StartBlockAddr := to_integer(normStartAddr(AddrWidthVar-1 downto BlockkWidthVar)) ; | |||
EndBlockAddr := to_integer( normEndAddr(AddrWidthVar-1 downto BlockkWidthVar)) ; | |||
else | |||
StartBlockAddr := 0 ; | |||
EndBlockAddr := 0 ; | |||
end if ; | |||
BlockAddrLoop : for BlockAddr in StartBlockAddr to EndBlockAddr loop | |||
next BlockAddrLoop when ArrayPtrVar(BlockAddr) = NULL ; | |||
if BlockAddr = StartBlockAddr then | |||
StartWordAddr := to_integer(normStartAddr(BlockkWidthVar-1 downto 0)) ; | |||
else | |||
StartWordAddr := 0 ; | |||
end if ; | |||
if BlockAddr = EndBlockAddr then | |||
EndWordAddr := to_integer(normEndAddr(BlockkWidthVar-1 downto 0)) ; | |||
else | |||
EndWordAddr := 2**BlockkWidthVar-1 ; | |||
end if ; | |||
FoundData := FALSE ; | |||
WordAddrLoop : for WordAddr in StartWordAddr to EndWordAddr loop | |||
if (ArrayPtrVar(BlockAddr)(WordAddr) < 0) then | |||
-- X in Word, return all X | |||
Data := (Data'range => 'X') ; | |||
FoundData := FALSE ; | |||
else | |||
-- Get the Word from the Array | |||
Data := to_slv(ArrayPtrVar(BlockAddr)(WordAddr), Data'length) ; | |||
if not FoundData then | |||
-- Write Address | |||
write(buf, '@') ; | |||
hwrite(buf, to_slv(BlockAddr, AddrWidthVar-BlockkWidthVar) & to_slv(WordAddr, BlockkWidthVar)) ; | |||
writeline(MemFile, buf) ; | |||
end if ; | |||
FoundData := TRUE ; | |||
end if ; | |||
if FoundData then -- Write Data | |||
if DataFormat = HEX then | |||
hwrite(buf, Data) ; | |||
writeline(MemFile, buf) ; | |||
else | |||
write(buf, Data) ; | |||
writeline(MemFile, buf) ; | |||
end if; | |||
end if ; | |||
end loop WordAddrLoop ; | |||
end loop BlockAddrLoop ; | |||
file_close(MemFile) ; | |||
end FileWriteX ; | |||
------------------------------------------------------------ | |||
procedure FileWriteH ( | |||
-- Hexadecimal File Write | |||
------------------------------------------------------------ | |||
FileName : string ; | |||
StartAddr : std_logic_vector ; | |||
EndAddr : std_logic_vector | |||
) is | |||
begin | |||
FileWriteX(FileName, HEX, StartAddr, EndAddr) ; | |||
end FileWriteH ; | |||
------------------------------------------------------------ | |||
procedure FileWriteH (FileName : string ; StartAddr : std_logic_vector) is | |||
-- Hexadecimal File Write | |||
------------------------------------------------------------ | |||
constant EndAddr : std_logic_vector(AddrWidthVar - 1 downto 0) := (others => '1') ; | |||
begin | |||
FileWriteX(FileName, HEX, StartAddr, EndAddr) ; | |||
end FileWriteH ; | |||
------------------------------------------------------------ | |||
procedure FileWriteH (FileName : string) is | |||
-- Hexadecimal File Write | |||
------------------------------------------------------------ | |||
constant StartAddr : std_logic_vector(AddrWidthVar - 1 downto 0) := (others => '0') ; | |||
constant EndAddr : std_logic_vector(AddrWidthVar - 1 downto 0) := (others => '1') ; | |||
begin | |||
FileWriteX(FileName, HEX, StartAddr, EndAddr) ; | |||
end FileWriteH ; | |||
------------------------------------------------------------ | |||
procedure FileWriteB ( | |||
-- Binary File Write | |||
------------------------------------------------------------ | |||
FileName : string ; | |||
StartAddr : std_logic_vector ; | |||
EndAddr : std_logic_vector | |||
) is | |||
begin | |||
FileWriteX(FileName, BINARY, StartAddr, EndAddr) ; | |||
end FileWriteB ; | |||
------------------------------------------------------------ | |||
procedure FileWriteB (FileName : string ; StartAddr : std_logic_vector) is | |||
-- Binary File Write | |||
------------------------------------------------------------ | |||
constant EndAddr : std_logic_vector(AddrWidthVar - 1 downto 0) := (others => '1') ; | |||
begin | |||
FileWriteX(FileName, BINARY, StartAddr, EndAddr) ; | |||
end FileWriteB ; | |||
------------------------------------------------------------ | |||
procedure FileWriteB (FileName : string) is | |||
-- Binary File Write | |||
------------------------------------------------------------ | |||
constant StartAddr : std_logic_vector(AddrWidthVar - 1 downto 0) := (others => '0') ; | |||
constant EndAddr : std_logic_vector(AddrWidthVar - 1 downto 0) := (others => '1') ; | |||
begin | |||
FileWriteX(FileName, BINARY, StartAddr, EndAddr) ; | |||
end FileWriteB ; | |||
end protected body MemoryPType ; | |||
end MemoryPkg ; |
@ -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 ; |
@ -0,0 +1,63 @@ | |||
-- | |||
-- File Name: OsvvmContext.vhd | |||
-- Design Unit Name: OsvvmContext | |||
-- Revision: STANDARD VERSION | |||
-- | |||
-- Maintainer: Jim Lewis email: jim@synthworks.com-- | |||
-- | |||
-- Description | |||
-- Context Declaration for OSVVM packages | |||
-- | |||
-- Developed by/for: | |||
-- SynthWorks Design Inc. | |||
-- VHDL Training Classes | |||
-- 11898 SW 128th Ave. Tigard, Or 97223 | |||
-- http://www.SynthWorks.com | |||
-- | |||
-- Latest standard version available at: | |||
-- http://www.SynthWorks.com/downloads | |||
-- | |||
-- Revision History: | |||
-- Date Version Description | |||
-- 01/2015 2015.01 Initial Revision | |||
-- 06/2015 2015.06 Added MemoryPkg | |||
-- 11/2016 2016.11 Added TbUtilPkg and ResolutionPkg | |||
-- | |||
-- | |||
-- Copyright (c) 2015 - 2016 by SynthWorks Design Inc. All rights reserved. | |||
-- | |||
-- Verbatim copies of this source file may be used and | |||
-- distributed without restriction. | |||
-- | |||
-- This source file is free software; you can redistribute it | |||
-- and/or modify it under the terms of the ARTISTIC License | |||
-- as published by The Perl Foundation; either version 2.0 of | |||
-- the License, or (at your option) any later version. | |||
-- | |||
-- This source is distributed in the hope that it will be | |||
-- useful, but WITHOUT ANY WARRANTY; without even the implied | |||
-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR | |||
-- PURPOSE. See the Artistic License for details. | |||
-- | |||
-- You should have received a copy of the license with this source. | |||
-- If not download it from, | |||
-- http://www.perlfoundation.org/artistic_license_2_0 | |||
-- | |||
-- | |||
context OsvvmContext is | |||
library OSVVM ; | |||
use OSVVM.NamePkg.all ; | |||
use OSVVM.TranscriptPkg.all ; | |||
use OSVVM.TextUtilPkg.all ; | |||
use OSVVM.OsvvmGlobalPkg.all ; | |||
use OSVVM.AlertLogPkg.all ; | |||
use OSVVM.RandomPkg.all ; | |||
use OSVVM.CoveragePkg.all ; | |||
use OSVVM.MemoryPkg.all ; | |||
use OSVVM.ResolutionPkg.all ; | |||
use OSVVM.TbUtilPkg.all ; | |||
end context OsvvmContext ; | |||
@ -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 ; |
@ -0,0 +1,392 @@ | |||
-- | |||
-- File Name: ResolutionPkg.vhd | |||
-- Design Unit Name: ResolutionPkg | |||
-- Revision: STANDARD VERSION | |||
-- | |||
-- Maintainer: Jim Lewis email: jim@SynthWorks.com | |||
-- Contributor(s): | |||
-- Jim Lewis email: jim@SynthWorks.com | |||
-- | |||
-- Package Defines | |||
-- resolved resolution functions for integer, real, and time | |||
-- types resolved_integer, resolved_real, resolved_time | |||
-- | |||
-- Developed for: | |||
-- SynthWorks Design Inc. | |||
-- VHDL Training Classes | |||
-- 11898 SW 128th Ave. Tigard, Or 97223 | |||
-- http://www.SynthWorks.com | |||
-- | |||
-- Revision History: | |||
-- Date Version Description | |||
-- 09/2006: 0.1 Initial revision | |||
-- Numerous revisions for VHDL Testbenches and Verification | |||
-- 02/2009: 1.0 VHDL-2008 STANDARD VERSION | |||
-- 05/2015 2015.05 Added Alerts | |||
-- -- Replaced Alerts with asserts as alerts are illegal in pure functions | |||
-- 11/2016 2016.11 Removed Asserts as they are not working as intended. | |||
-- See ResolutionPkg_debug as it uses Alerts to correctly detect errors | |||
-- | |||
-- | |||
-- Copyright (c) 2005 - 2016 by SynthWorks Design Inc. All rights reserved. | |||
-- | |||
-- Verbatim copies of this source file may be used and | |||
-- distributed without restriction. | |||
-- | |||
-- This source file may be modified and distributed under | |||
-- the terms of the ARTISTIC License as published by | |||
-- The Perl Foundation; either version 2.0 of the License, | |||
-- or (at your option) any later version. | |||
-- | |||
-- This source is distributed in the hope that it will be | |||
-- useful, but WITHOUT ANY WARRANTY; without even the implied | |||
-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR | |||
-- PURPOSE. See the Artistic License for details. | |||
-- | |||
-- You should have received a copy of the license with this source. | |||
-- If not download it from, | |||
-- http://www.perlfoundation.org/artistic_license_2_0 | |||
-- | |||
library ieee ; | |||
use ieee.std_logic_1164.all ; | |||
use ieee.numeric_std.all ; | |||
library osvvm ; | |||
use osvvm.AlertLogPkg.all ; | |||
package ResolutionPkg is | |||
constant MULTIPLE_DRIVER_SEVERITY : severity_level := ERROR ; | |||
-- | |||
-- Note that not all simulators support resolution functions of the form: | |||
-- subtype std_logic_vector_max is (resolved_max) std_ulogic_vector ; | |||
-- | |||
-- Hence, types of the form are offered as a temporary workaround until they do: | |||
-- std_logic_vector_max_c is array (natural range <>) of std_logic_max ; -- for non VHDL-2008 | |||
-- | |||
-- resolved_max | |||
-- return maximum value. | |||
-- No initializations required on ports, default of type'left is ok | |||
function resolved_max ( s : std_ulogic_vector) return std_ulogic ; | |||
subtype std_logic_max is resolved_max std_ulogic ; | |||
subtype std_logic_vector_max is (resolved_max) std_ulogic_vector ; | |||
type std_logic_vector_max_c is array (natural range <>) of std_logic_max ; -- for non VHDL-2008 | |||
subtype unsigned_max is (resolved_max) unresolved_unsigned ; | |||
type unsigned_max_c is array (natural range <>) of std_logic_max ; -- for non VHDL-2008 | |||
subtype signed_max is (resolved_max) unresolved_signed ; | |||
type signed_max_c is array (natural range <>) of std_logic_max ; -- for non VHDL-2008 | |||
function resolved_max ( s : bit_vector) return bit ; | |||
subtype bit_max is resolved_max bit ; | |||
subtype bit_vector_max is (resolved_max) bit_vector ; | |||
type bit_vector_max_c is array (natural range <>) of bit_max ; -- for non VHDL-2008 | |||
function resolved_max ( s : integer_vector ) return integer ; | |||
subtype integer_max is resolved_max integer ; | |||
subtype integer_vector_max is (resolved_max) integer_vector ; | |||
type integer_vector_max_c is array (natural range <>) of integer_max ; -- for non VHDL-2008 | |||
function resolved_max ( s : time_vector ) return time ; | |||
subtype time_max is resolved_max time ; | |||
subtype time_vector_max is (resolved_max) time_vector ; | |||
type time_vector_max_c is array (natural range <>) of time_max ; -- for non VHDL-2008 | |||
function resolved_max ( s : real_vector ) return real ; | |||
subtype real_max is resolved_max real ; | |||
subtype real_vector_max is (resolved_max) real_vector ; | |||
type real_vector_max_c is array (natural range <>) of real_max ; -- for non VHDL-2008 | |||
function resolved_max ( s : string) return character ; | |||
subtype character_max is resolved_max character ; | |||
subtype string_max is (resolved_max) string ; | |||
type string_max_c is array (positive range <>) of character_max ; -- for non VHDL-2008 | |||
function resolved_max ( s : boolean_vector) return boolean ; | |||
subtype boolean_max is resolved_max boolean ; | |||
subtype boolean_vector_max is (resolved_max) boolean_vector ; | |||
type boolean_vector_max_c is array (natural range <>) of boolean_max ; -- for non VHDL-2008 | |||
-- return sum of values that /= type'left | |||
-- No initializations required on ports, default of type'left is ok | |||
function resolved_sum ( s : integer_vector ) return integer ; | |||
subtype integer_sum is resolved_sum integer ; | |||
subtype integer_vector_sum is (resolved_sum) integer_vector ; | |||
type integer_vector_sum_c is array (natural range <>) of integer_sum ; -- for non VHDL-2008 | |||
function resolved_sum ( s : time_vector ) return time ; | |||
subtype time_sum is resolved_sum time ; | |||
subtype time_vector_sum is (resolved_sum) time_vector ; | |||
type time_vector_sum_c is array (natural range <>) of time_sum ; -- for non VHDL-2008 | |||
function resolved_sum ( s : real_vector ) return real ; | |||
subtype real_sum is resolved_sum real ; | |||
subtype real_vector_sum is (resolved_sum) real_vector ; | |||
type real_vector_sum_c is array (natural range <>) of real_sum ; -- for non VHDL-2008 | |||
-- resolved_weak | |||
-- Special just for std_ulogic | |||
-- No initializations required on ports, default of type'left is ok | |||
function resolved_weak (s : std_ulogic_vector) return std_ulogic ; -- no init, type'left | |||
subtype std_logic_weak is resolved_weak std_ulogic ; | |||
subtype std_logic_vector_weak is (resolved_weak) std_ulogic_vector ; | |||
-- legacy stuff | |||
-- requires ports to be initialized to 0 in the appropriate type. | |||
function resolved ( s : integer_vector ) return integer ; | |||
subtype resolved_integer is resolved integer ; | |||
function resolved ( s : time_vector ) return time ; | |||
subtype resolved_time is resolved time ; | |||
function resolved ( s : real_vector ) return real ; | |||
subtype resolved_real is resolved real ; | |||
function resolved (s : string) return character ; -- same as resolved_max | |||
subtype resolved_character is resolved character ; | |||
-- subtype resolved_string is (resolved) string ; -- subtype will replace type later | |||
type resolved_string is array (positive range <>) of resolved_character; -- will change to subtype -- assert but no init | |||
function resolved ( s : boolean_vector) return boolean ; --same as resolved_max | |||
subtype resolved_boolean is resolved boolean ; | |||
end package ResolutionPkg ; | |||
package body ResolutionPkg is | |||
-- resolved_max | |||
-- return maximum value. Assert FAILURE if more than 1 /= type'left | |||
-- No initializations required on ports, default of type'left is ok | |||
-- Optimized version is just the following: | |||
-- ------------------------------------------------------------ | |||
-- function resolved_max ( s : <array_type> ) return <element_type> is | |||
-- ------------------------------------------------------------ | |||
-- begin | |||
-- return maximum(s) ; | |||
-- end function resolved_max ; | |||
------------------------------------------------------------ | |||
function resolved_max (s : std_ulogic_vector) return std_ulogic is | |||
------------------------------------------------------------ | |||
begin | |||
return maximum(s) ; | |||
end function resolved_max ; | |||
------------------------------------------------------------ | |||
function resolved_max ( s : bit_vector ) return bit is | |||
------------------------------------------------------------ | |||
begin | |||
return maximum(s) ; | |||
end function resolved_max ; | |||
------------------------------------------------------------ | |||
function resolved_max ( s : integer_vector ) return integer is | |||
------------------------------------------------------------ | |||
begin | |||
return maximum(s) ; | |||
end function resolved_max ; | |||
------------------------------------------------------------ | |||
function resolved_max ( s : time_vector ) return time is | |||
------------------------------------------------------------ | |||
begin | |||
return maximum(s) ; | |||
end function resolved_max ; | |||
------------------------------------------------------------ | |||
function resolved_max ( s : real_vector ) return real is | |||
------------------------------------------------------------ | |||
begin | |||
return maximum(s) ; | |||
end function resolved_max ; | |||
------------------------------------------------------------ | |||
function resolved_max ( s : string ) return character is | |||
------------------------------------------------------------ | |||
begin | |||
return maximum(s) ; | |||
end function resolved_max ; | |||
------------------------------------------------------------ | |||
function resolved_max ( s : boolean_vector) return boolean is | |||
------------------------------------------------------------ | |||
begin | |||
return maximum(s) ; | |||
end function resolved_max ; | |||
-- resolved_sum - appropriate for numeric types | |||
-- return sum of values that /= type'left | |||
-- No initializations required on ports, default of type'left is ok | |||
------------------------------------------------------------ | |||
function resolved_sum ( s : integer_vector ) return integer is | |||
------------------------------------------------------------ | |||
variable result : integer := 0 ; | |||
begin | |||
for i in s'RANGE loop | |||
if s(i) /= integer'left then | |||
result := s(i) + result; | |||
end if ; | |||
end loop ; | |||
return result ; | |||
end function resolved_sum ; | |||
------------------------------------------------------------ | |||
function resolved_sum ( s : time_vector ) return time is | |||
------------------------------------------------------------ | |||
variable result : time := 0 sec ; | |||
begin | |||
for i in s'RANGE loop | |||
if s(i) /= time'left then | |||
result := s(i) + result; | |||
end if ; | |||
end loop ; | |||
return result ; | |||
end function resolved_sum ; | |||
------------------------------------------------------------ | |||
function resolved_sum ( s : real_vector ) return real is | |||
------------------------------------------------------------ | |||
variable result : real := 0.0 ; | |||
begin | |||
for i in s'RANGE loop | |||
if s(i) /= real'left then | |||
result := s(i) + result; | |||
end if ; | |||
end loop ; | |||
return result ; | |||
end function resolved_sum ; | |||
-- resolved_weak | |||
-- Special just for std_ulogic | |||
-- No initializations required on ports, default of type'left is ok | |||
type stdlogic_table is array(STD_ULOGIC, STD_ULOGIC) of STD_ULOGIC; | |||
constant weak_resolution_table : stdlogic_table := ( | |||
-- Resolution order: Z < U < W < X < - < L < H < 0 < 1 | |||
-- --------------------------------------------------------- | |||
-- | U X 0 1 Z W L H - | | | |||
-- --------------------------------------------------------- | |||
('U', 'X', '0', '1', 'U', 'W', 'L', 'H', '-'), -- | U | | |||
('X', 'X', '0', '1', 'X', 'X', 'L', 'H', '-'), -- | X | | |||
('0', '0', '0', '1', '0', '0', '0', '0', '0'), -- | 0 | | |||
('1', '1', '1', '1', '1', '1', '1', '1', '1'), -- | 1 | | |||
('U', 'X', '0', '1', 'Z', 'W', 'L', 'H', '-'), -- | Z | | |||
('W', 'X', '0', '1', 'W', 'W', 'L', 'H', '-'), -- | W | | |||
('L', 'L', '0', '1', 'L', 'L', 'L', 'H', 'L'), -- | L | | |||
('H', 'H', '0', '1', 'H', 'H', 'W', 'H', 'H'), -- | H | | |||
('-', '-', '0', '1', '-', '-', 'L', 'H', '-') -- | - | | |||
); | |||
------------------------------------------------------------ | |||
function resolved_weak (s : std_ulogic_vector) return std_ulogic is | |||
------------------------------------------------------------ | |||
variable result : std_ulogic := 'Z' ; | |||
begin | |||
for i in s'RANGE loop | |||
result := weak_resolution_table(result, s(i)) ; | |||
end loop ; | |||
return result ; | |||
end function resolved_weak ; | |||
-- legacy stuff. | |||
-- requires ports to be initialized to 0 in the appropriate type. | |||
------------------------------------------------------------ | |||
function resolved ( s : integer_vector ) return integer is | |||
-- requires interface to be initialized to 0 | |||
------------------------------------------------------------ | |||
variable result : integer := 0 ; | |||
variable failed : boolean := FALSE ; | |||
begin | |||
for i in s'RANGE loop | |||
if s(i) /= 0 then | |||
failed := failed or (result /= 0) ; | |||
result := maximum(s(i),result); | |||
end if ; | |||
end loop ; | |||
assert not failed report "ResolutionPkg.resolved: multiple drivers on integer" severity MULTIPLE_DRIVER_SEVERITY ; | |||
-- AlertIf(OSVVM_ALERTLOG_ID, failed, "ResolutionPkg.resolved: multiple drivers on integer") ; | |||
return result ; | |||
end function resolved ; | |||
------------------------------------------------------------ | |||
function resolved ( s : time_vector ) return time is | |||
-- requires interface to be initialized to 0 ns | |||
------------------------------------------------------------ | |||
variable result : time := 0 ns ; | |||
variable failed : boolean := FALSE ; | |||
begin | |||
for i in s'RANGE loop | |||
if s(i) > 0 ns then | |||
failed := failed or (result /= 0 ns) ; | |||
result := maximum(s(i),result); | |||
end if ; | |||
end loop ; | |||
assert not failed report "ResolutionPkg.resolved: multiple drivers on time" severity MULTIPLE_DRIVER_SEVERITY ; | |||
-- AlertIf(OSVVM_ALERTLOG_ID, failed, "ResolutionPkg.resolved: multiple drivers on time") ; | |||
return result ; | |||
end function resolved ; | |||
------------------------------------------------------------ | |||
function resolved ( s : real_vector ) return real is | |||
-- requires interface to be initialized to 0.0 | |||
------------------------------------------------------------ | |||
variable result : real := 0.0 ; | |||
variable failed : boolean := FALSE ; | |||
begin | |||
for i in s'RANGE loop | |||
if s(i) /= 0.0 then | |||
failed := failed or (result /= 0.0) ; | |||
result := maximum(s(i),result); | |||
end if ; | |||
end loop ; | |||
assert not failed report "ResolutionPkg.resolved: multiple drivers on real" severity MULTIPLE_DRIVER_SEVERITY ; | |||
-- AlertIf(OSVVM_ALERTLOG_ID, failed, "ResolutionPkg.resolved: multiple drivers on real") ; | |||
return result ; | |||
end function resolved ; | |||
------------------------------------------------------------ | |||
function resolved (s : string) return character is | |||
-- same as resolved_max | |||
------------------------------------------------------------ | |||
variable result : character := NUL ; | |||
variable failed : boolean := FALSE ; | |||
begin | |||
for i in s'RANGE loop | |||
if s(i) /= NUL then | |||
failed := failed or (result /= NUL) ; | |||
result := maximum(result, s(i)) ; | |||
end if ; | |||
end loop ; | |||
assert not failed report "ResolutionPkg.resolved: multiple drivers on character" severity MULTIPLE_DRIVER_SEVERITY ; | |||
-- AlertIf(OSVVM_ALERTLOG_ID, failed, "ResolutionPkg.resolved: multiple drivers on character") ; | |||
return result ; | |||
end function resolved ; | |||
------------------------------------------------------------ | |||
function resolved ( s : boolean_vector) return boolean is | |||
-- same as resolved_max | |||
------------------------------------------------------------ | |||
variable result : boolean := FALSE ; | |||
variable failed : boolean := FALSE ; | |||
begin | |||
for i in s'RANGE loop | |||
if s(i) then | |||
failed := failed or result ; | |||
result := TRUE ; | |||
end if ; | |||
end loop ; | |||
assert not failed report "ResolutionPkg.resolved: multiple drivers on boolean" severity MULTIPLE_DRIVER_SEVERITY ; | |||
-- AlertIf(OSVVM_ALERTLOG_ID, failed, "ResolutionPkg.resolved: multiple drivers on boolean") ; | |||
return result ; | |||
end function resolved ; | |||
end package body ResolutionPkg ; |
@ -0,0 +1,65 @@ | |||
-- | |||
-- File Name: ScoreBoardPkg_int.vhd | |||
-- Design Unit Name: ScoreBoardPkg_int | |||
-- Revision: STANDARD VERSION | |||
-- | |||
-- Maintainer: Jim Lewis email: jim@synthworks.com | |||
-- Contributor(s): | |||
-- Jim Lewis email: jim@synthworks.com | |||
-- | |||
-- | |||
-- Description: | |||
-- Instance of Generic Package ScoreboardGenericPkg for integer | |||
-- | |||
-- Developed for: | |||
-- SynthWorks Design Inc. | |||
-- VHDL Training Classes | |||
-- 11898 SW 128th Ave. Tigard, Or 97223 | |||
-- http://www.SynthWorks.com | |||
-- | |||
-- Latest standard version available at: | |||
-- http://www.SynthWorks.com/downloads | |||
-- | |||
-- Revision History: | |||
-- Date Version Description | |||
-- 08/2012 2012.08 Generic Instance of ScoreboardGenericPkg | |||
-- 08/2014 2013.08 Updated interface for Match and to_string | |||
-- 11/2016 2016.11 Released as part of OSVVM library | |||
-- | |||
-- | |||
-- Copyright (c) 2006 - 2016 by SynthWorks Design Inc. All rights reserved. | |||
-- | |||
-- Verbatim copies of this source file may be used and | |||
-- distributed without restriction. | |||
-- | |||
-- This source file is free software; you can redistribute it | |||
-- and/or modify it under the terms of the ARTISTIC License | |||
-- as published by The Perl Foundation; either version 2.0 of | |||
-- the License, or (at your option) any later version. | |||
-- | |||
-- This source is distributed in the hope that it will be | |||
-- useful, but WITHOUT ANY WARRANTY; without even the implied | |||
-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR | |||
-- PURPOSE. See the Artistic License for details. | |||
-- | |||
-- You should have received a copy of the license with this source. | |||
-- If not download it from, | |||
-- http://www.perlfoundation.org/artistic_license_2_0 | |||
-- | |||
-- | |||
use std.textio.all ; | |||
library ieee ; | |||
use ieee.std_logic_1164.all ; | |||
use ieee.numeric_std.all ; | |||
package ScoreBoardPkg_int is new work.ScoreboardGenericPkg | |||
generic map ( | |||
ExpectedType => integer, | |||
ActualType => integer, | |||
Match => "=", | |||
expected_to_string => to_string, | |||
actual_to_string => to_string | |||
) ; |
@ -0,0 +1,65 @@ | |||
-- | |||
-- File Name: ScoreBoardPkg_slv.vhd | |||
-- Design Unit Name: ScoreBoardPkg_slv | |||
-- Revision: STANDARD VERSION | |||
-- | |||
-- Maintainer: Jim Lewis email: jim@synthworks.com | |||
-- Contributor(s): | |||
-- Jim Lewis email: jim@synthworks.com | |||
-- | |||
-- | |||
-- Description: | |||
-- Instance of Generic Package ScoreboardGenericPkg for std_logic_vector | |||
-- | |||
-- Developed for: | |||
-- SynthWorks Design Inc. | |||
-- VHDL Training Classes | |||
-- 11898 SW 128th Ave. Tigard, Or 97223 | |||
-- http://www.SynthWorks.com | |||
-- | |||
-- Latest standard version available at: | |||
-- http://www.SynthWorks.com/downloads | |||
-- | |||
-- Revision History: | |||
-- Date Version Description | |||
-- 08/2012 2012.08 Generic Instance of ScoreboardGenericPkg | |||
-- 08/2014 2013.08 Updated interface for Match and to_string | |||
-- 11/2016 2016.11 Released as part of OSVVM library | |||
-- | |||
-- | |||
-- Copyright (c) 2006 - 2016 by SynthWorks Design Inc. All rights reserved. | |||
-- | |||
-- Verbatim copies of this source file may be used and | |||
-- distributed without restriction. | |||
-- | |||
-- This source file is free software; you can redistribute it | |||
-- and/or modify it under the terms of the ARTISTIC License | |||
-- as published by The Perl Foundation; either version 2.0 of | |||
-- the License, or (at your option) any later version. | |||
-- | |||
-- This source is distributed in the hope that it will be | |||
-- useful, but WITHOUT ANY WARRANTY; without even the implied | |||
-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR | |||
-- PURPOSE. See the Artistic License for details. | |||
-- | |||
-- You should have received a copy of the license with this source. | |||
-- If not download it from, | |||
-- http://www.perlfoundation.org/artistic_license_2_0 | |||
-- | |||
-- | |||
use std.textio.all ; | |||
library ieee ; | |||
use ieee.std_logic_1164.all ; | |||
use ieee.numeric_std.all ; | |||
package ScoreBoardPkg_slv is new work.ScoreboardGenericPkg | |||
generic map ( | |||
ExpectedType => std_logic_vector, | |||
ActualType => std_logic_vector, | |||
Match => std_match, -- "=", [std_logic_vector, std_logic_vector return boolean] | |||
expected_to_string => to_hstring, -- [std_logic_vector return string] | |||
actual_to_string => to_hstring -- [std_logic_vector return string] | |||
) ; |
@ -0,0 +1,851 @@ | |||
-- | |||
-- File Name: TbUtilPkg.vhd | |||
-- Design Unit Name: TbUtilPkg | |||
-- Revision: STANDARD VERSION | |||
-- | |||
-- Maintainer: Jim Lewis email: jim@SynthWorks.com | |||
-- Contributor(s): | |||
-- Jim Lewis email: jim@SynthWorks.com | |||
-- | |||
-- Package Defines | |||
-- | |||
-- Developed for: | |||
-- SynthWorks Design Inc. | |||
-- VHDL Training Classes | |||
-- 11898 SW 128th Ave. Tigard, Or 97223 | |||
-- http://www.SynthWorks.com | |||
-- | |||
-- Revision History: | |||
-- Date Version Description | |||
-- 11/1999: 0.1 Initial revision | |||
-- Numerous revisions for VHDL Testbenches and Verification | |||
-- 10/2013 2013.10 Split out Text Utilities | |||
-- 11/2016 2016.11 First Public Release Version | |||
-- Updated naming for consistency. | |||
-- | |||
-- | |||
-- Copyright (c) 1999 - 2016 by SynthWorks Design Inc. All rights reserved. | |||
-- | |||
-- Verbatim copies of this source file may be used and | |||
-- distributed without restriction. | |||
-- | |||
-- This source file is free software; you can redistribute it | |||
-- and/or modify it under the terms of the ARTISTIC License | |||
-- as published by The Perl Foundation; either version 2.0 of | |||
-- the License, or (at your option) any later version. | |||
-- | |||
-- This source is distributed in the hope that it will be | |||
-- useful, but WITHOUT ANY WARRANTY; without even the implied | |||
-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR | |||
-- PURPOSE. See the Artistic License for details. | |||
-- | |||
-- You should have received a copy of the license with this source. | |||
-- If not download it from, | |||
-- http://www.perlfoundation.org/artistic_license_2_0 | |||
-- | |||
library ieee ; | |||
use ieee.std_logic_1164.all ; | |||
library osvvm ; | |||
use osvvm.AlertLogPkg.all ; | |||
use osvvm.TranscriptPkg.all ; | |||
package TbUtilPkg is | |||
constant CLK_ACTIVE : std_logic := '1' ; | |||
constant t_sim_resolution : time := std.env.resolution_limit ; -- VHDL-2008 | |||
-- constant t_sim_resolution : time := 1 ns ; -- for non VHDL-2008 simulators | |||
------------------------------------------------------------ | |||
-- ZeroOneHot, OneHot | |||
-- OneHot: return true if exactly one value is 1 | |||
-- ZeroOneHot: return false when more than one value is a 1 | |||
------------------------------------------------------------ | |||
function OneHot ( constant A : in std_logic_vector ) return boolean ; | |||
function ZeroOneHot ( constant A : in std_logic_vector ) return boolean ; | |||
------------------------------------------------------------ | |||
-- RequestTransaction | |||
-- Transaction initiation side of handshaking | |||
-- Pairs with WaitForTransaction or one of its variations | |||
------------------------------------------------------------ | |||
procedure RequestTransaction ( | |||
signal Rdy : Out std_logic ; | |||
signal Ack : In std_logic | |||
) ; | |||
------------------------------------------------------------ | |||
-- WaitForTransaction | |||
-- Model side of handshaking | |||
-- Pairs with RequestTransaction | |||
------------------------------------------------------------ | |||
procedure WaitForTransaction ( | |||
signal Clk : In std_logic ; | |||
signal Rdy : In std_logic ; | |||
signal Ack : Out std_logic | |||
) ; | |||
-- Variation for model that stops waiting when TimeOut is asserted | |||
-- Intended for models that need to switch between instruction streams | |||
-- such as a CPU when interrupt is pending | |||
procedure WaitForTransaction ( | |||
signal Clk : In std_logic ; | |||
signal Rdy : In std_logic ; | |||
signal Ack : Out std_logic ; | |||
signal TimeOut : In std_logic ; | |||
constant Polarity : In std_logic := '1' | |||
) ; | |||
-- Set Ack to Model starting value | |||
procedure StartTransaction ( signal Ack : Out std_logic ) ; | |||
-- Set Ack to Model finishing value | |||
procedure FinishTransaction ( signal Ack : Out std_logic ) ; | |||
-- If a transaction is pending, return true | |||
function TransactionPending ( signal Rdy : In std_logic ) return boolean ; | |||
-- Variation for clockless models | |||
procedure WaitForTransaction ( | |||
signal Rdy : In std_logic ; | |||
signal Ack : Out std_logic | |||
) ; | |||
------------------------------------------------------------ | |||
-- Toggle, WaitForToggle | |||
-- Used for communicating between processes | |||
------------------------------------------------------------ | |||
procedure Toggle ( | |||
signal Sig : InOut std_logic ; | |||
constant DelayVal : time | |||
) ; | |||
procedure Toggle ( signal Sig : InOut std_logic ) ; | |||
procedure ToggleHS ( signal Sig : InOut std_logic ) ; | |||
function IsToggle ( signal Sig : In std_logic ) return boolean ; | |||
procedure WaitForToggle ( signal Sig : In std_logic ) ; | |||
-- Bit type versions | |||
procedure Toggle ( signal Sig : InOut bit ; constant DelayVal : time ) ; | |||
procedure Toggle ( signal Sig : InOut bit ) ; | |||
procedure ToggleHS ( signal Sig : InOut bit ) ; | |||
function IsToggle ( signal Sig : In bit ) return boolean ; | |||
procedure WaitForToggle ( signal Sig : In bit ) ; | |||
------------------------------------------------------------ | |||
-- WaitForBarrier | |||
-- Barrier Synchronization | |||
-- Multiple processes call it, it finishes when all have called it | |||
------------------------------------------------------------ | |||
procedure WaitForBarrier ( signal Sig : InOut std_logic ) ; | |||
procedure WaitForBarrier ( signal Sig : InOut std_logic ; signal TimeOut : std_logic ; constant Polarity : in std_logic := '1') ; | |||
procedure WaitForBarrier ( signal Sig : InOut std_logic ; constant TimeOut : time ) ; | |||
-- resolved_barrier : summing resolution used in conjunction with integer based barriers | |||
function resolved_barrier ( s : integer_vector ) return integer ; | |||
subtype integer_barrier is resolved_barrier integer ; | |||
-- Usage of integer barriers requires resolved_barrier. Initialization to 1 recommended, but not required | |||
-- signal barrier1 : resolved_barrier integer := 1 ; -- using the resolution function | |||
-- signal barrier2 : integer_barrier := 1 ; -- using the subtype that already applies the resolution function | |||
procedure WaitForBarrier ( signal Sig : InOut integer ) ; | |||
procedure WaitForBarrier ( signal Sig : InOut integer ; signal TimeOut : std_logic ; constant Polarity : in std_logic := '1') ; | |||
procedure WaitForBarrier ( signal Sig : InOut integer ; constant TimeOut : time ) ; | |||
-- Using separate signals | |||
procedure WaitForBarrier2 ( signal SyncOut : out std_logic ; signal SyncIn : in std_logic ) ; | |||
procedure WaitForBarrier2 ( signal SyncOut : out std_logic ; signal SyncInV : in std_logic_vector ) ; | |||
------------------------------------------------------------ | |||
-- WaitForClock | |||
-- Sync to Clock - after a delay, after a number of clocks | |||
------------------------------------------------------------ | |||
procedure WaitForClock ( signal Clk : in std_logic ; constant Delay : in time ) ; | |||
procedure WaitForClock ( signal Clk : in std_logic ; constant NumberOfClocks : in integer := 1) ; | |||
procedure WaitForClock ( signal Clk : in std_logic ; signal Enable : in boolean ) ; | |||
procedure WaitForClock ( signal Clk : in std_logic ; signal Enable : in std_logic ; constant Polarity : std_logic := '1' ) ; | |||
------------------------------------------------------------ | |||
-- WaitForLevel | |||
-- Find a signal at a level | |||
------------------------------------------------------------ | |||
procedure WaitForLevel ( signal A : in boolean ) ; | |||
procedure WaitForLevel ( signal A : in std_logic ; Polarity : std_logic := '1' ) ; | |||
------------------------------------------------------------ | |||
-- CreateClock, CreateReset | |||
-- Note these do not exit | |||
------------------------------------------------------------ | |||
procedure CreateClock ( | |||
signal Clk : inout std_logic ; | |||
constant Period : time ; | |||
constant DutyCycle : real := 0.5 | |||
) ; | |||
procedure CheckClockPeriod ( | |||
constant AlertLogID : AlertLogIDType ; | |||
signal Clk : in std_logic ; | |||
constant Period : time ; | |||
constant ClkName : string := "Clock" ; | |||
constant HowMany : integer := 5 | |||
) ; | |||
procedure CheckClockPeriod ( | |||
signal Clk : in std_logic ; | |||
constant Period : time ; | |||
constant ClkName : string := "Clock" ; | |||
constant HowMany : integer := 5 | |||
) ; | |||
procedure CreateReset ( | |||
signal Reset : out std_logic ; | |||
constant ResetActive : in std_logic ; | |||
signal Clk : in std_logic ; | |||
constant Period : time ; | |||
constant tpd : time | |||
) ; | |||
procedure LogReset ( | |||
constant AlertLogID : AlertLogIDType ; | |||
signal Reset : in std_logic ; | |||
constant ResetActive : in std_logic ; | |||
constant ResetName : in string := "Reset" ; | |||
constant LogLevel : in LogType := ALWAYS | |||
) ; | |||
procedure LogReset ( | |||
signal Reset : in std_logic ; | |||
constant ResetActive : in std_logic ; | |||
constant ResetName : in string := "Reset" ; | |||
constant LogLevel : in LogType := ALWAYS | |||
) ; | |||
------------------------------------------------------------ | |||
-- Deprecated subprogram names | |||
-- Maintaining backward compatibility using aliases | |||
------------------------------------------------------------ | |||
-- History of RequestTransaction / WaitForTransaction | |||
alias RequestAction is RequestTransaction [std_logic, std_logic] ; | |||
alias WaitForRequest is WaitForTransaction [std_logic, std_logic, std_logic] ; | |||
-- History of WaitForToggle | |||
alias WaitOnToggle is WaitForToggle [std_logic] ; | |||
-- History of WaitForBarrier | |||
alias WayPointBlock is WaitForBarrier [std_logic] ; | |||
alias SyncTo is WaitForBarrier2[std_logic, std_logic] ; | |||
alias SyncTo is WaitForBarrier2[std_logic, std_logic_vector] ; | |||
-- Backward compatible name | |||
alias SyncToClk is WaitForClock [std_logic, time] ; | |||
------------------------------------------------------------ | |||
-- Deprecated | |||
-- subsumed by WaitForTransaction with Ack and TimeOut. | |||
-- TimeOut works exactly like IntReq | |||
------------------------------------------------------------ | |||
procedure WaitForTransactionOrIrq ( | |||
signal Clk : In std_logic ; | |||
signal Rdy : In std_logic ; | |||
signal IntReq : In std_logic | |||
) ; | |||
------------------------------------------------------------ | |||
-- Deprecated | |||
-- WaitForAck, StrobeAck | |||
-- Replaced by WaitForToggle and Toggle | |||
------------------------------------------------------------ | |||
procedure WaitForAck ( signal Ack : In std_logic ) ; | |||
procedure StrobeAck ( signal Ack : Out std_logic ) ; | |||
end TbUtilPkg ; | |||
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |||
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |||
package body TbUtilPkg is | |||
------------------------------------------------------------ | |||
-- ZeroOneHot, OneHot | |||
-- OneHot: return true if exactly one value is 1 | |||
-- ZeroOneHot: return false when more than one value is a 1 | |||
------------------------------------------------------------ | |||
function OneHot ( constant A : in std_logic_vector ) return boolean is | |||
variable found_one : boolean := FALSE ; | |||
begin | |||
for i in A'range loop | |||
if A(i) = '1' or A(i) = 'H' then | |||
if found_one then | |||
return FALSE ; | |||
end if ; | |||
found_one := TRUE ; | |||
end if ; | |||
end loop ; | |||
return found_one ; -- found a one | |||
end function OneHot ; | |||
function ZeroOneHot ( constant A : in std_logic_vector ) return boolean is | |||
variable found_one : boolean := FALSE ; | |||
begin | |||
for i in A'range loop | |||
if A(i) = '1' or A(i) = 'H' then | |||
if found_one then | |||
return FALSE ; | |||
end if ; | |||
found_one := TRUE ; | |||
end if ; | |||
end loop ; | |||
return TRUE ; -- all zero or found a one | |||
end function ZeroOneHot ; | |||
------------------------------------------------------------ | |||
-- RequestTransaction | |||
-- Transaction initiation side of handshaking | |||
-- Pairs with WaitForTransaction or one of its variations | |||
------------------------------------------------------------ | |||
procedure RequestTransaction ( | |||
signal Rdy : Out std_logic ; | |||
signal Ack : In std_logic | |||
) is | |||
begin | |||
-- Record contains new transaction | |||
Rdy <= '1' ; | |||
-- Find Ack low = '0' | |||
wait until Ack = '0' ; | |||
-- Prepare for Next Transaction | |||
Rdy <= '0' ; | |||
-- Transaction Done | |||
wait until Ack = '1' ; | |||
end procedure ; | |||
------------------------------------------------------------ | |||
-- WaitForTransaction | |||
-- Model side of handshaking | |||
-- Pairs with RequestTransaction | |||
------------------------------------------------------------ | |||
procedure WaitForTransaction ( | |||
signal Clk : In std_logic ; | |||
signal Rdy : In std_logic ; | |||
signal Ack : Out std_logic | |||
) is | |||
variable AckTime : time ; | |||
begin | |||
-- End of Previous Cycle. Signal Done | |||
Ack <= '1' ; -- #6 | |||
AckTime := NOW ; | |||
-- Find Start of Transaction | |||
if Rdy /= '1' then -- #2 | |||
wait until Rdy = '1' ; | |||
else | |||
wait for 0 ns ; -- allow Ack to update | |||
end if ; | |||
-- align to clock if needed (not back-to-back transactions) | |||
if NOW /= AckTime then | |||
wait until Clk = CLK_ACTIVE ; | |||
end if ; | |||
-- Model active and owns the record | |||
Ack <= '0' ; -- #3 | |||
end procedure ; | |||
-- Variation for model that stops waiting when TimeOut is asserted | |||
-- Intended for models that need to switch between instruction streams | |||
-- such as a CPU when interrupt is pending | |||
procedure WaitForTransaction ( | |||
signal Clk : In std_logic ; | |||
signal Rdy : In std_logic ; | |||
signal Ack : Out std_logic ; | |||
signal TimeOut : In std_logic ; | |||
constant Polarity : In std_logic := '1' | |||
) is | |||
variable AckTime : time ; | |||
variable FoundRdy : boolean ; | |||
begin | |||
-- End of Previous Cycle. Signal Done | |||
Ack <= '1' ; -- #6 | |||
AckTime := NOW ; | |||
-- Find Ready or Time out | |||
if (Rdy /= '1' and TimeOut /= Polarity) then | |||
wait until Rdy = '1' or TimeOut = Polarity ; | |||
else | |||
wait for 0 ns ; -- allow Ack to update | |||
end if ; | |||
FoundRdy := Rdy = '1' ; | |||
-- align to clock if Rdy or TimeOut does not happen within delta cycles from Ack | |||
if NOW /= AckTime then | |||
wait until Clk = CLK_ACTIVE ; | |||
end if ; | |||
if FoundRdy then | |||
-- Model active and owns the record | |||
Ack <= '0' ; -- #3 | |||
end if ; | |||
end procedure ; | |||
-- Set Ack to Model starting value | |||
-- Pairs with WaitForTransactionOrIrq above | |||
procedure StartTransaction ( signal Ack : Out std_logic ) is | |||
begin | |||
Ack <= '0' ; | |||
end procedure ; | |||
-- Set Ack to Model finishing value | |||
-- Pairs with WaitForTransactionOrIrq above | |||
procedure FinishTransaction ( signal Ack : Out std_logic ) is | |||
begin | |||
-- End of Cycle | |||
Ack <= '1' ; | |||
end procedure ; | |||
-- If a transaction is pending, return true | |||
-- Used to detect presence of transaction stream, | |||
-- such as an interrupt handler | |||
function TransactionPending ( | |||
signal Rdy : In std_logic | |||
) return boolean is | |||
begin | |||
return Rdy = '1' ; | |||
end function ; | |||
-- Variation for clockless models | |||
procedure WaitForTransaction ( | |||
signal Rdy : In std_logic ; | |||
signal Ack : Out std_logic | |||
) is | |||
variable AckTime : time ; | |||
begin | |||
-- End of Previous Cycle. Signal Done | |||
Ack <= '1' ; -- #6 | |||
-- Find Start of Transaction | |||
if Rdy /= '1' then -- #2 | |||
wait until Rdy = '1' ; | |||
else | |||
wait for 0 ns ; -- allow Ack to update | |||
end if ; | |||
-- Model active and owns the record | |||
Ack <= '0' ; -- #3 | |||
end procedure ; | |||
------------------------------------------------------------ | |||
-- Toggle, WaitForToggle | |||
-- Used for communicating between processes | |||
------------------------------------------------------------ | |||
type stdulogic_indexby_stdulogic is array (std_ulogic) of std_ulogic; | |||
constant toggle_sl_table : stdulogic_indexby_stdulogic := ( | |||
'0' => '1', | |||
'L' => '1', | |||
others => '0' | |||
); | |||
procedure Toggle ( | |||
signal Sig : InOut std_logic ; | |||
constant DelayVal : time | |||
) is | |||
variable iDelayVal : time ; | |||
begin | |||
iDelayVal := DelayVal ; | |||
if iDelayVal > t_sim_resolution then | |||
iDelayVal := iDelayVal - t_sim_resolution ; | |||
end if ; | |||
Sig <= toggle_sl_table(Sig) after iDelayVal ; | |||
end procedure ; | |||
procedure Toggle ( signal Sig : InOut std_logic ) is | |||
begin | |||
Sig <= toggle_sl_table(Sig) ; | |||
end procedure ; | |||
procedure ToggleHS ( signal Sig : InOut std_logic ) is | |||
begin | |||
Sig <= toggle_sl_table(Sig) ; | |||
wait for 0 ns ; -- Sig toggles | |||
wait for 0 ns ; -- new values updated into record | |||
end procedure ; | |||
function IsToggle ( signal Sig : In std_logic ) return boolean is | |||
begin | |||
return Sig'event ; | |||
end function ; | |||
procedure WaitForToggle ( signal Sig : In std_logic ) is | |||
begin | |||
wait on Sig ; | |||
end procedure ; | |||
-- Bit type versions | |||
procedure Toggle ( signal Sig : InOut bit ; constant DelayVal : time ) is | |||
variable iDelayVal : time ; | |||
begin | |||
iDelayVal := DelayVal ; | |||
if iDelayVal > t_sim_resolution then | |||
iDelayVal := iDelayVal - t_sim_resolution ; | |||
end if ; | |||
Sig <= not Sig after iDelayVal ; | |||
end procedure ; | |||
procedure Toggle ( signal Sig : InOut bit ) is | |||
begin | |||
Sig <= not Sig ; | |||
end procedure ; | |||
procedure ToggleHS ( signal Sig : InOut bit ) is | |||
begin | |||
Sig <= not Sig ; | |||
wait for 0 ns ; -- Sig toggles | |||
wait for 0 ns ; -- new values updated into record | |||
end procedure ; | |||
function IsToggle ( signal Sig : In bit ) return boolean is | |||
begin | |||
return Sig'event ; | |||
end function ; | |||
procedure WaitForToggle ( signal Sig : In bit ) is | |||
begin | |||
wait on Sig ; | |||
end procedure ; | |||
------------------------------------------------------------ | |||
-- WaitForBarrier | |||
-- Barrier Synchronization | |||
-- Multiple processes call it, it finishes when all have called it | |||
------------------------------------------------------------ | |||
procedure WaitForBarrier ( signal Sig : InOut std_logic ) is | |||
begin | |||
Sig <= 'H' ; | |||
-- Wait until all processes set Sig to H | |||
-- Level check not necessary since last value /= H yet | |||
wait until Sig = 'H' ; | |||
-- Deactivate and propagate to allow back to back calls | |||
Sig <= '0' ; | |||
wait for 0 ns ; | |||
end procedure WaitForBarrier ; | |||
procedure WaitForBarrier ( signal Sig : InOut std_logic ; signal TimeOut : std_logic ; constant Polarity : in std_logic := '1') is | |||
begin | |||
Sig <= 'H' ; | |||
-- Wait until all processes set Sig to H | |||
-- Level check not necessary since last value /= H yet | |||
wait until Sig = 'H' or TimeOut = Polarity ; | |||
-- Deactivate and propagate to allow back to back calls | |||
Sig <= '0' ; | |||
wait for 0 ns ; | |||
end procedure WaitForBarrier ; | |||
procedure WaitForBarrier ( signal Sig : InOut std_logic ; constant TimeOut : time ) is | |||
begin | |||
Sig <= 'H' ; | |||
-- Wait until all processes set Sig to H | |||
-- Level check not necessary since last value /= H yet | |||
wait until Sig = 'H' for TimeOut ; | |||
-- Deactivate and propagate to allow back to back calls | |||
Sig <= '0' ; | |||
wait for 0 ns ; | |||
end procedure WaitForBarrier ; | |||
------------------------------------------------------------ | |||
-- resolved_barrier | |||
-- summing resolution used in conjunction with integer based barriers | |||
function resolved_barrier ( s : integer_vector ) return integer is | |||
variable result : integer := 0 ; | |||
begin | |||
for i in s'RANGE loop | |||
if s(i) /= integer'left then | |||
result := s(i) + result; | |||
else | |||
return integer'left ; -- removes the initialization requirement | |||
end if ; | |||
end loop ; | |||
return result ; | |||
end function resolved_barrier ; | |||
-- Usage of integer barriers requires resolved_barrier. Initialization to 1 recommended, but not required | |||
-- signal barrier1 : resolved_barrier integer := 1 ; -- using the resolution function | |||
-- signal barrier2 : integer_barrier := 1 ; -- using the subtype that already applies the resolution function | |||
procedure WaitForBarrier ( signal Sig : InOut integer ) is | |||
begin | |||
Sig <= 0 ; | |||
-- Wait until all processes set Sig to 0 | |||
-- Level check not necessary since last value /= 0 yet | |||
wait until Sig = 0 ; | |||
-- Deactivate and propagate to allow back to back calls | |||
Sig <= 1 ; | |||
wait for 0 ns ; | |||
end procedure WaitForBarrier ; | |||
procedure WaitForBarrier ( signal Sig : InOut integer ; signal TimeOut : std_logic ; constant Polarity : in std_logic := '1') is | |||
begin | |||
Sig <= 0 ; | |||
-- Wait until all processes set Sig to 0 | |||
-- Level check not necessary since last value /= 0 yet | |||
wait until Sig = 0 or TimeOut = Polarity ; | |||
-- Deactivate and propagate to allow back to back calls | |||
Sig <= 1 ; | |||
wait for 0 ns ; | |||
end procedure WaitForBarrier ; | |||
procedure WaitForBarrier ( signal Sig : InOut integer ; constant TimeOut : time ) is | |||
begin | |||
Sig <= 0 ; | |||
-- Wait until all processes set Sig to 0 | |||
-- Level check not necessary since last value /= 0 yet | |||
wait until Sig = 0 for TimeOut ; | |||
-- Deactivate and propagate to allow back to back calls | |||
Sig <= 1 ; | |||
wait for 0 ns ; | |||
end procedure WaitForBarrier ; | |||
-- Using separate signals | |||
procedure WaitForBarrier2 ( signal SyncOut : out std_logic ; signal SyncIn : in std_logic ) is | |||
begin | |||
-- Activate Rdy | |||
SyncOut <= '1' ; | |||
-- Make sure our Rdy is seen | |||
wait for 0 ns ; | |||
-- Wait until other process' Rdy is at level 1 | |||
if SyncIn /= '1' then | |||
wait until SyncIn = '1' ; | |||
end if ; | |||
-- Deactivate Rdy | |||
SyncOut <= '0' ; | |||
end procedure WaitForBarrier2 ; | |||
procedure WaitForBarrier2 ( signal SyncOut : out std_logic ; signal SyncInV : in std_logic_vector ) is | |||
constant ALL_ONE : std_logic_vector(SyncInV'Range) := (others => '1'); | |||
begin | |||
-- Activate Rdy | |||
SyncOut <= '1' ; | |||
-- Make sure our Rdy is seen | |||
wait for 0 ns ; | |||
-- Wait until all other process' Rdy is at level 1 | |||
if SyncInV /= ALL_ONE then | |||
wait until SyncInV = ALL_ONE ; | |||
end if ; | |||
-- Deactivate Rdy | |||
SyncOut <= '0' ; | |||
end procedure WaitForBarrier2 ; | |||
------------------------------------------------------------ | |||
-- WaitForClock | |||
-- Sync to Clock - after a delay, after a number of clocks | |||
------------------------------------------------------------ | |||
procedure WaitForClock ( signal Clk : in std_logic ; constant Delay : in time ) is | |||
begin | |||
if delay > t_sim_resolution then | |||
wait for delay - t_sim_resolution ; | |||
end if ; | |||
wait until Clk = CLK_ACTIVE ; | |||
end procedure WaitForClock ; | |||
procedure WaitForClock ( signal Clk : in std_logic ; constant NumberOfClocks : in integer := 1) is | |||
begin | |||
for i in 1 to NumberOfClocks loop | |||
wait until Clk = CLK_ACTIVE ; | |||
end loop ; | |||
end procedure WaitForClock ; | |||
procedure WaitForClock ( signal Clk : in std_logic ; signal Enable : in boolean ) is | |||
begin | |||
wait on Clk until Clk = CLK_ACTIVE and Enable ; | |||
end procedure WaitForClock ; | |||
procedure WaitForClock ( signal Clk : in std_logic ; signal Enable : in std_logic ; constant Polarity : std_logic := '1' ) is | |||
begin | |||
wait on Clk until Clk = CLK_ACTIVE and Enable = Polarity ; | |||
end procedure WaitForClock ; | |||
------------------------------------------------------------ | |||
-- WaitForLevel | |||
-- Find a signal at a level | |||
------------------------------------------------------------ | |||
procedure WaitForLevel ( signal A : in boolean ) is | |||
begin | |||
if not A then | |||
wait until A ; | |||
end if ; | |||
end procedure WaitForLevel ; | |||
procedure WaitForLevel ( signal A : in std_logic ; Polarity : std_logic := '1' ) is | |||
begin | |||
if A /= Polarity then | |||
-- wait on A until A = Polarity ; | |||
if Polarity = '1' then | |||
wait until A = '1' ; | |||
else | |||
wait until A = '0' ; | |||
end if ; | |||
end if ; | |||
end procedure WaitForLevel ; | |||
------------------------------------------------------------ | |||
-- CreateClock, CreateReset | |||
-- Note these do not exit | |||
------------------------------------------------------------ | |||
procedure CreateClock ( | |||
signal Clk : inout std_logic ; | |||
constant Period : time ; | |||
constant DutyCycle : real := 0.5 | |||
) is | |||
constant HIGH_TIME : time := Period * DutyCycle ; | |||
constant LOW_TIME : time := Period - HIGH_TIME ; | |||
begin | |||
if HIGH_TIME = LOW_TIME then | |||
loop | |||
Clk <= toggle_sl_table(Clk) after HIGH_TIME ; | |||
wait on Clk ; | |||
end loop ; | |||
else | |||
-- Schedule s.t. all assignments after the first occur on delta cycle 0 | |||
Clk <= '0', '1' after LOW_TIME ; | |||
wait for period - 1 ns ; -- allows after on future Clk <= '0' | |||
loop | |||
Clk <= '0' after 1 ns, '1' after LOW_TIME + 1 ns ; | |||
wait for period ; | |||
end loop ; | |||
end if ; | |||
end procedure CreateClock ; | |||
procedure CheckClockPeriod ( | |||
constant AlertLogID : AlertLogIDType ; | |||
signal Clk : in std_logic ; | |||
constant Period : time ; | |||
constant ClkName : string := "Clock" ; | |||
constant HowMany : integer := 5 | |||
) is | |||
variable LastLogTime, ObservedPeriod : time ; | |||
begin | |||
wait until Clk = CLK_ACTIVE ; | |||
LastLogTime := now ; | |||
-- Check First HowMany clocks | |||
for i in 1 to HowMany loop | |||
wait until Clk = CLK_ACTIVE ; | |||
ObservedPeriod := now - LastLogTime ; | |||
AffirmIf(AlertLogID, ObservedPeriod = Period, | |||
"CheckClockPeriod: " & ClkName & " Period: " & to_string(ObservedPeriod) & | |||
" = Expected " & to_string(Period)) ; | |||
LastLogTime := now ; | |||
end loop ; | |||
wait ; | |||
end procedure CheckClockPeriod ; | |||
procedure CheckClockPeriod ( | |||
signal Clk : in std_logic ; | |||
constant Period : time ; | |||
constant ClkName : string := "Clock" ; | |||
constant HowMany : integer := 5 | |||
) is | |||
begin | |||
CheckClockPeriod ( | |||
AlertLogID => ALERTLOG_DEFAULT_ID, | |||
Clk => Clk, | |||
Period => Period, | |||
ClkName => ClkName, | |||
HowMany => HowMany | |||
) ; | |||
end procedure CheckClockPeriod ; | |||
procedure CreateReset ( | |||
signal Reset : out std_logic ; | |||
constant ResetActive : in std_logic ; | |||
signal Clk : in std_logic ; | |||
constant Period : time ; | |||
constant tpd : time | |||
) is | |||
begin | |||
wait until Clk = CLK_ACTIVE ; | |||
Reset <= ResetActive after tpd ; | |||
wait for Period - t_sim_resolution ; | |||
wait until Clk = CLK_ACTIVE ; | |||
Reset <= not ResetActive after tpd ; | |||
wait ; | |||
end procedure CreateReset ; | |||
procedure LogReset ( | |||
constant AlertLogID : AlertLogIDType ; | |||
signal Reset : in std_logic ; | |||
constant ResetActive : in std_logic ; | |||
constant ResetName : in string := "Reset" ; | |||
constant LogLevel : in LogType := ALWAYS | |||
) is | |||
begin | |||
-- Does not log the value of Reset at time 0. | |||
for_ever : loop | |||
wait on Reset ; | |||
if Reset = ResetActive then | |||
LOG(AlertLogID, ResetName & " now active", INFO) ; | |||
print("") ; | |||
elsif Reset = not ResetActive then | |||
LOG(AlertLogID, ResetName & " now inactive", INFO) ; | |||
print("") ; | |||
else | |||
LOG(AlertLogID, ResetName & " = " & to_string(Reset), INFO) ; | |||
print("") ; | |||
end if ; | |||
end loop for_ever ; | |||
end procedure LogReset ; | |||
procedure LogReset ( | |||
signal Reset : in std_logic ; | |||
constant ResetActive : in std_logic ; | |||
constant ResetName : in string := "Reset" ; | |||
constant LogLevel : in LogType := ALWAYS | |||
) is | |||
begin | |||
LogReset ( | |||
AlertLogID => ALERTLOG_DEFAULT_ID, | |||
Reset => Reset, | |||
ResetActive => ResetActive, | |||
ResetName => ResetName, | |||
LogLevel => LogLevel | |||
) ; | |||
end procedure LogReset ; | |||
------------------------------------------------------------ | |||
-- Deprecated | |||
-- subsumed by WaitForTransaction with Ack and TimeOut. | |||
-- TimeOut works exactly like IntReq | |||
------------------------------------------------------------ | |||
procedure WaitForTransactionOrIrq ( | |||
signal Clk : In std_logic ; | |||
signal Rdy : In std_logic ; | |||
signal IntReq : In std_logic | |||
) is | |||
variable AckTime : time ; | |||
constant POLARITY : std_logic := '1' ; | |||
begin | |||
AckTime := NOW ; | |||
-- Find Ready or Time out | |||
if (Rdy /= '1' and IntReq /= POLARITY) then | |||
wait until Rdy = '1' or IntReq = POLARITY ; | |||
else | |||
wait for 0 ns ; -- allow Ack to update | |||
end if ; | |||
-- align to clock if Rdy or IntReq does not happen within delta cycles from Ack | |||
if NOW /= AckTime then | |||
wait until Clk = CLK_ACTIVE ; | |||
end if ; | |||
end procedure ; | |||
------------------------------------------------------------ | |||
-- Deprecated | |||
-- WaitForAck, StrobeAck | |||
-- Replaced by WaitForToggle and Toggle | |||
------------------------------------------------------------ | |||
procedure WaitForAck ( signal Ack : In std_logic ) is | |||
begin | |||
-- Wait for Model to be done | |||
wait until Ack = '1' ; | |||
end procedure ; | |||
procedure StrobeAck ( signal Ack : Out std_logic ) is | |||
begin | |||
-- Model done, drive rising edge on Ack | |||
Ack <= '0' ; | |||
wait for 0 ns ; | |||
Ack <= '1' ; | |||
end procedure ; | |||
end TbUtilPkg ; | |||
@ -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 ; |
@ -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 ; |
@ -0,0 +1,120 @@ | |||
-- | |||
-- File Name: VendorCovApiPkg.vhd | |||
-- Design Unit Name: VendorCovApiPkg | |||
-- Revision: STANDARD VERSION | |||
-- | |||
-- Maintainer: Jim Lewis email: jim@synthworks.com | |||
-- | |||
-- Based on work done in package VendorCovApiPkg_Aldec.vhd by: | |||
-- ... | |||
-- | |||
-- | |||
-- Package Defines | |||
-- A set of foreign procedures that link OSVVM's CoveragePkg | |||
-- coverage model creation and coverage capture with the | |||
-- built-in capability of a simulator. | |||
-- | |||
-- | |||
-- Revision History: For more details, see CoveragePkg_release_notes.pdf | |||
-- Date Version Description | |||
-- 11/2016: 2016.11 Initial revision | |||
-- | |||
-- | |||
-- Copyright (c) 2016 by SynthWorks Design Inc. All rights reserved. | |||
-- | |||
-- Verbatim copies of this source file may be used and | |||
-- distributed without restriction. | |||
-- | |||
-- Modified copies of this source file may be distributed | |||
-- under the terms of the ARTISTIC License as published by | |||
-- The Perl Foundation; either version 2.0 of the License, | |||
-- or (at your option) any later version. | |||
-- | |||
-- This source is distributed in the hope that it will be | |||
-- useful, but WITHOUT ANY WARRANTY; without even the implied | |||
-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR | |||
-- PURPOSE. See the Artistic License for details. | |||
-- | |||
-- You should have received a copy of the license with this source. | |||
-- If not download it from, | |||
-- http://www.perlfoundation.org/artistic_license_2_0 | |||
-- -- | |||
-------------------------------------------------------------------------- | |||
package VendorCovApiPkg is | |||
subtype VendorCovHandleType is integer; | |||
-- Types for how coverage bins are represented. Matches OSVVM types. | |||
type VendorCovRangeType is record | |||
min: integer; | |||
max: integer; | |||
end record; | |||
type VendorCovRangeArrayType is array ( integer range <> ) of VendorCovRangeType; | |||
-- Create Initial Data Structure for Point/Item Functional Coverage Model | |||
-- Sets initial name of the coverage model if available | |||
impure function VendorCovPointCreate( name: string ) return VendorCovHandleType; | |||
-- Create Initial Data Structure for Cross Functional Coverage Model | |||
-- Sets initial name of the coverage model if available | |||
impure function VendorCovCrossCreate( name: string ) return VendorCovHandleType; | |||
-- Sets/Updates the name of the Coverage Model. | |||
-- Should not be called until the data structure is created by VendorCovPointCreate or VendorCovCrossCreate. | |||
-- Replaces name that was set by VendorCovPointCreate or VendorCovCrossCreate. | |||
procedure VendorCovSetName( obj: VendorCovHandleType; name: string ); | |||
-- Add a bin or set of bins to either a Point/Item or Cross Functional Coverage Model | |||
-- Checking for sizing that is different from original sizing already done in OSVVM CoveragePkg | |||
-- It is important to maintain an index that corresponds to the order the bins were entered as | |||
-- that is used when coverage is recorded. | |||
procedure VendorCovBinAdd( obj: VendorCovHandleType; bins: VendorCovRangeArrayType; Action: integer; atleast: integer; name: string ); | |||
-- Increment the coverage of bin identified by index number. | |||
-- Index ranges from 1 to Number of Bins. | |||
-- Index corresponds to the order the bins were entered (starting from 1) | |||
procedure VendorCovBinInc( obj: VendorCovHandleType; index: integer ); | |||
end package; | |||
package body VendorCovApiPkg is | |||
-- Create Initial Data Structure for Point/Item Functional Coverage Model | |||
-- Sets initial name of the coverage model if available | |||
impure function VendorCovPointCreate( name: string ) return VendorCovHandleType is | |||
begin | |||
return 0 ; | |||
end function VendorCovPointCreate ; | |||
-- Create Initial Data Structure for Cross Functional Coverage Model | |||
-- Sets initial name of the coverage model if available | |||
impure function VendorCovCrossCreate( name: string ) return VendorCovHandleType is | |||
begin | |||
return 0 ; | |||
end function VendorCovCrossCreate ; | |||
-- Sets/Updates the name of the Coverage Model. | |||
-- Should not be called until the data structure is created by VendorCovPointCreate or VendorCovCrossCreate. | |||
-- Replaces name that was set by VendorCovPointCreate or VendorCovCrossCreate. | |||
procedure VendorCovSetName( obj: VendorCovHandleType; name: string ) is | |||
begin | |||
end procedure VendorCovSetName ; | |||
-- Add a bin or set of bins to either a Point/Item or Cross Functional Coverage Model | |||
-- Checking for sizing that is different from original sizing already done in OSVVM CoveragePkg | |||
-- It is important to maintain an index that corresponds to the order the bins were entered as | |||
-- that is used when coverage is recorded. | |||
procedure VendorCovBinAdd( obj: VendorCovHandleType; bins: VendorCovRangeArrayType; Action: integer; atleast: integer; name: string )is | |||
begin | |||
end procedure VendorCovBinAdd ; | |||
-- Increment the coverage of bin identified by index number. | |||
-- Index ranges from 1 to Number of Bins. | |||
-- Index corresponds to the order the bins were entered (starting from 1) | |||
procedure VendorCovBinInc( obj: VendorCovHandleType; index: integer )is | |||
begin | |||
end procedure VendorCovBinInc ; | |||
end package body VendorCovApiPkg ; |
@ -0,0 +1,92 @@ | |||
-- | |||
-- File Name: VendorCovApiPkg_Aldec.vhd | |||
-- Design Unit Name: VendorCovApiPkg | |||
-- Revision: ALDEC VERSION | |||
-- | |||
-- Maintainer: | |||
-- | |||
-- Package Defines | |||
-- A set of foreign procedures that link OSVVM's CoveragePkg | |||
-- coverage model creation and coverage capture with the | |||
-- built-in capability of a simulator. | |||
-- | |||
-- | |||
-- Revision History: For more details, see CoveragePkg_release_notes.pdf | |||
-- Date Version Description | |||
-- 11/2016: 2016.11 Initial revision | |||
-- 12/2016 2016.11a Fixed an issue with attributes | |||
-- | |||
-- | |||
-- Copyright (c) 2016 by Aldec. All rights reserved. | |||
-- | |||
-- Verbatim copies of this source file may be used and | |||
-- distributed without restriction. | |||
-- | |||
-- Modified copies of this source file may be distributed | |||
-- under the terms of the ARTISTIC License as published by | |||
-- The Perl Foundation; either version 2.0 of the License, | |||
-- or (at your option) any later version. | |||
-- | |||
-- This source is distributed in the hope that it will be | |||
-- useful, but WITHOUT ANY WARRANTY; without even the implied | |||
-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR | |||
-- PURPOSE. See the Artistic License for details. | |||
-- | |||
-- You should have received a copy of the license with this source. | |||
-- If not download it from, | |||
-- http://www.perlfoundation.org/artistic_license_2_0 | |||
-- -- | |||
-------------------------------------------------------------------------- | |||
package VendorCovApiPkg is | |||
subtype VendorCovHandleType is integer; | |||
-- Types for how coverage bins are represented. Matches OSVVM types. | |||
type VendorCovRangeType is record | |||
min: integer; | |||
max: integer; | |||
end record; | |||
type VendorCovRangeArrayType is array ( integer range <> ) of VendorCovRangeType; | |||
-- Create Initial Data Structure for Point/Item Functional Coverage Model | |||
-- Sets initial name of the coverage model if available | |||
impure function VendorCovPointCreate( name: string ) return VendorCovHandleType; | |||
attribute foreign of VendorCovPointCreate[ string return VendorCovHandleType ]: function is "VHPI systf; cvg_CvpCreate"; | |||
-- Create Initial Data Structure for Cross Functional Coverage Model | |||
-- Sets initial name of the coverage model if available | |||
impure function VendorCovCrossCreate( name: string ) return VendorCovHandleType; | |||
attribute foreign of VendorCovCrossCreate[ string return VendorCovHandleType ]: function is "VHPI systf; cvg_CrCreate"; | |||
-- Sets/Updates the name of the Coverage Model. | |||
-- Should not be called until the data structure is created by VendorCovPointCreate or VendorCovCrossCreate. | |||
-- Replaces name that was set by VendorCovPointCreate or VendorCovCrossCreate. | |||
procedure VendorCovSetName( obj: VendorCovHandleType; name: string ); | |||
attribute foreign of VendorCovSetName[ VendorCovHandleType, string ]: procedure is "VHPI systf; cvg_SetCoverName"; | |||
-- Add a bin or set of bins to either a Point/Item or Cross Functional Coverage Model | |||
-- Checking for sizing that is different from original sizing already done in OSVVM CoveragePkg | |||
-- It is important to maintain an index that corresponds to the order the bins were entered as | |||
-- that is used when coverage is recorded. | |||
procedure VendorCovBinAdd( obj: VendorCovHandleType; bins: VendorCovRangeArrayType; Action: integer; atleast: integer; name: string ); | |||
attribute foreign of VendorCovBinAdd[ VendorCovHandleType, VendorCovRangeArrayType, integer, integer, string ]: procedure is "VHPI systf; cvg_CvpCrBinCreate"; | |||
-- Increment the coverage of bin identified by index number. | |||
-- Index ranges from 1 to Number of Bins. | |||
-- Index corresponds to the order the bins were entered (starting from 1) | |||
procedure VendorCovBinInc( obj: VendorCovHandleType; index: integer ); | |||
attribute foreign of VendorCovBinInc[ VendorCovHandleType, integer ]: procedure is "VHPI systf; cvg_CvpCrBinIncr"; | |||
-- Action (integer): | |||
-- constant COV_COUNT : integer := 1; | |||
-- constant COV_IGNORE : integer := 0; | |||
-- constant COV_ILLEGAL : integer := -1; | |||
end package; | |||
package body VendorCovApiPkg is | |||
-- Replace any existing package body for this package | |||
end package body VendorCovApiPkg ; |