summaryrefslogtreecommitdiff
path: root/vhdl/fmf/memory.vhd
diff options
context:
space:
mode:
Diffstat (limited to 'vhdl/fmf/memory.vhd')
-rw-r--r--vhdl/fmf/memory.vhd714
1 files changed, 714 insertions, 0 deletions
diff --git a/vhdl/fmf/memory.vhd b/vhdl/fmf/memory.vhd
new file mode 100644
index 0000000..4b19e85
--- /dev/null
+++ b/vhdl/fmf/memory.vhd
@@ -0,0 +1,714 @@
+--------------------------------------------------------------------------------
+-- File Name: memory.vhd
+--------------------------------------------------------------------------------
+-- Copyright (C) 2001-2005 Free Model Foundry; http://www.FreeModelFoundry.com
+--
+-- This program is free software; you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License version 2 as
+-- published by the Free Software Foundation.
+--
+-- MODIFICATION HISTORY:
+--
+-- version: | author: | mod date: | changes made:
+-- V0.1 R. Munden 01 NOV 01 Initial beta release
+-- V0.2 R. Munden 01 NOV 24 refined Table_generic_sram
+-- V0.3 R. Munden 02 MAR 23 added Table_2_cntrl_sram
+-- V0.4 A. Savic 05 JUN 15 extended for memory management routines
+-- extended for routine comments
+-- V0.5 R. Munden 06 JUN 04 corrected memory management routines
+-- per Sergey Sulyutin
+--
+--------------------------------------------------------------------------------
+LIBRARY IEEE; USE IEEE.std_logic_1164.ALL;
+ USE IEEE.VITAL_primitives.ALL;
+ USE IEEE.VITAL_timing.ALL;
+ USE IEEE.vital_memory.ALL;
+
+--------------------------------------------------------------------------------
+PACKAGE memory IS
+
+ ----------------------------------------------------------------------------
+ -- Asynchronous SRAM with low chip enable and write enable
+ ----------------------------------------------------------------------------
+ CONSTANT Table_2_cntrl_sram : VitalMemoryTableType := (
+
+ -- ----------------------------------------------------------
+ -- CEN, WEN, Addr, DI, act, DO
+ -- ----------------------------------------------------------
+ -- Address initiated read
+ ( '0', '1', 'G', '-', 's', 'm' ),
+ ( '0', '1', 'U', '-', 's', 'l' ),
+
+ -- CEN initiated read
+ ( 'N', '1', 'g', '-', 's', 'm' ),
+ ( 'N', '1', 'u', '-', 's', 'l' ),
+
+ -- Write Enable initiated Write
+ ( '0', 'P', 'g', '-', 'w', 'm' ),
+ ( '0', 'N', '-', '-', 's', 'Z' ),
+
+ -- CEN initiated Write
+ ( 'P', '0', 'g', '-', 'w', 'Z' ),
+ ( 'N', '0', '-', '-', 's', 'Z' ),
+
+ -- Address change during write
+ ( '0', '0', '*', '-', 'c', 'Z' ),
+ ( '0', 'X', '*', '-', 'c', 'Z' ),
+
+ -- if WEN is X
+ ( '0', 'X', 'g', '*', 'e', 'e' ),
+ ( '0', 'X', 'u', '*', 'c', 'l' ),
+
+ -- CEN is unasserted
+ ( 'X', '0', 'G', '-', 'e', 'Z' ),
+ ( 'X', '0', 'u', '-', 'c', 'Z' ),
+ ( 'X', '1', '-', '-', 's', 'l' ),
+ ( '1', '-', '-', '-', 's', 'Z' )
+
+ ); -- end of VitalMemoryTableType definition
+
+ ----------------------------------------------------------------------------
+ -- Asynchronous SRAM with high and low chip enables and output enable
+ ----------------------------------------------------------------------------
+ CONSTANT Table_generic_sram : VitalMemoryTableType := (
+
+ -- ----------------------------------------------------------
+ -- CE, CEN, OEN, WEN, Addr, DI, act, DO
+ -- ----------------------------------------------------------
+ -- Address initiated read
+ ( '1', '0', '0', '1', 'G', '-', 's', 'm' ),
+ ( '1', '0', '0', '1', 'U', '-', 's', 'l' ),
+
+ -- Output Enable initiated read
+ ( '1', '0', 'N', '1', 'g', '-', 's', 'm' ),
+ ( '1', '0', 'N', '1', 'u', '-', 's', 'l' ),
+ ( '1', '0', '0', '1', 'g', '-', 's', 'm' ),
+
+ -- CE initiated read
+ ( 'P', '0', '0', '1', 'g', '-', 's', 'm' ),
+ ( 'P', '0', '0', '1', 'u', '-', 's', 'l' ),
+
+ -- CEN initiated read
+ ( '1', 'N', '0', '1', 'g', '-', 's', 'm' ),
+ ( '1', 'N', '0', '1', 'u', '-', 's', 'l' ),
+
+ -- Write Enable Implicit Read
+ ( '1', '0', '0', 'P', '-', '-', 's', 'M' ),
+
+ -- Write Enable initiated Write
+ ( '1', '0', '1', 'N', 'g', '-', 'w', 'S' ),
+ ( '1', '0', '1', 'N', 'u', '-', 'c', 'S' ),
+
+ -- CE initiated Write
+ ( 'P', '0', '1', '0', 'g', '-', 'w', 'S' ),
+ ( 'P', '0', '1', '0', 'u', '-', 'c', 'S' ),
+
+ -- CEN initiated Write
+ ( '1', 'N', '1', '0', 'g', '-', 'w', 'Z' ),
+ ( '1', 'N', '1', '0', 'u', '-', 'c', 'Z' ),
+
+ -- Address change during write
+ ( '1', '0', '1', '0', '*', '-', 'c', 'Z' ),
+ ( '1', '0', '1', 'X', '*', '-', 'c', 'Z' ),
+
+ -- data initiated Write
+ ( '1', '0', '1', '0', 'g', '*', 'w', 'Z' ),
+ ( '1', '0', '1', '0', 'u', '-', 'c', 'Z' ),
+ ( '1', '0', '-', 'X', 'g', '*', 'e', 'e' ),
+ ( '1', '0', '-', 'X', 'u', '*', 'c', 'S' ),
+
+ -- if WEN is X
+ ( '1', '0', '1', 'r', 'g', '*', 'e', 'e' ),
+ ( '1', '0', '1', 'r', 'u', '*', 'c', 'l' ),
+ ( '1', '0', '-', 'r', 'g', '*', 'e', 'S' ),
+ ( '1', '0', '-', 'r', 'u', '*', 'c', 'S' ),
+ ( '1', '0', '1', 'f', 'g', '*', 'e', 'e' ),
+ ( '1', '0', '1', 'f', 'u', '*', 'c', 'l' ),
+ ( '1', '0', '-', 'f', 'g', '*', 'e', 'S' ),
+ ( '1', '0', '-', 'f', 'u', '*', 'c', 'S' ),
+
+ -- OEN is unasserted
+ ( '-', '-', '1', '-', '-', '-', 's', 'Z' ),
+ ( '1', '0', 'P', '-', '-', '-', 's', 'Z' ),
+ ( '1', '0', 'r', '-', '-', '-', 's', 'l' ),
+ ( '1', '0', 'f', '-', '-', '-', 's', 'l' ),
+ ( '1', '0', '1', '-', '-', '-', 's', 'Z' ),
+
+ -- CE is unasserted
+ ( '0', '-', '-', '-', '-', '-', 's', 'Z' ),
+ ( 'N', '0', '-', '-', '-', '-', 's', 'Z' ),
+ ( 'f', '0', '-', '-', '-', '-', 's', 'l' ),
+ ( 'r', '0', '-', '-', '-', '-', 's', 'l' ),
+ ( '0', '0', '-', '-', '-', '-', 's', 'Z' ),
+
+ -- CEN is unasserted
+ ( '-', '1', '-', '-', '-', '-', 's', 'Z' ),
+ ( '1', 'P', '-', '-', '-', '-', 's', 'Z' ),
+ ( '1', 'r', '-', '-', '-', '-', 's', 'l' ),
+ ( '1', 'f', '-', '-', '-', '-', 's', 'l' ),
+ ( '1', '1', '-', '-', '-', '-', 's', 'Z' )
+
+ ); -- end of VitalMemoryTableType definition
+
+ -- -------------------------------------------------------------------------
+ -- Memory data initial value.
+ -- Default value may be overridden by conigure_memory procedure
+ -- -------------------------------------------------------------------------
+ SHARED VARIABLE max_data : NATURAL := 16#FF#;
+
+ -- -------------------------------------------------------------------------
+ -- Data types required to implement link list structure
+ -- -------------------------------------------------------------------------
+ TYPE mem_data_t;
+ TYPE mem_data_pointer_t IS ACCESS mem_data_t;
+ TYPE mem_data_t IS RECORD
+ key_address : INTEGER;
+ val_data : INTEGER;
+ successor : mem_data_pointer_t;
+ END RECORD;
+
+ -- -------------------------------------------------------------------------
+ -- Array of linked lists.
+ -- Support memory region partitioning for faster access.
+ -- -------------------------------------------------------------------------
+ TYPE mem_data_pointer_array_t IS
+ ARRAY(NATURAL RANGE <>) OF mem_data_pointer_t;
+
+ -- -------------------------------------------------------------------------
+ --
+ -- Function Name: configure_memory
+ --
+ -- Description: Override mechanism default parameter values.
+ -- configure_memory routine is used to override default
+ -- memory initialization package parameter.
+ --
+ -- The value of max_data parameter value refers to memory
+ -- initial data value, memory data width dependent.
+ --
+ -- Arguments:
+ --
+ -- IN Type Description
+ -- max_data_c integer Memory data initial value.
+ -- The default is set to FFh.
+ --
+ -- INOUT
+ -- none
+ --
+ -- OUT
+ -- none
+ --
+ -- Returns
+ -- none
+ --
+ -- -------------------------------------------------------------------------
+ PROCEDURE configure_memory(
+ max_data_c : IN INTEGER);
+
+ -- -------------------------------------------------------------------------
+ --
+ -- Function Name: corrupt_mem
+ --
+ -- Description: corrupt_mem is used to perform memory data CORRUPT
+ -- operation above memory block or memory page region.
+ --
+ -- Routine is built-in addressing performance parameters.
+ -- Routine performs N successive corrupt operations.
+ -- For N successive corrupt operations instead of :
+ -- N x find + N x corrupt -->
+ -- corrupt_mem provides the posiibility of :
+ -- 1 x find + N x iterate + N x corrupt
+ -- Reducing the number of find element calls, operation
+ -- execution time is significantly affected.
+ --
+ -- [address_low, adress_high] must belong to the same
+ -- memory parition, handled by a single list.
+ --
+ -- Arguments:
+ --
+ -- IN Type Description
+ -- address_low integer Starting address of the memory
+ -- region to be corrupted.
+ -- address_high integer The last address of the memory
+ -- region to be corrupted.
+ --
+ -- INOUT
+ -- linked_list mem_data_pointer_t Linked list holding memory region
+ -- to be corrupted.
+ --
+ -- OUT
+ -- none
+ --
+ -- Returns
+ -- none
+ --
+ -- -------------------------------------------------------------------------
+ PROCEDURE corrupt_mem(
+ address_low : IN INTEGER;
+ address_high : IN INTEGER;
+ linked_list : INOUT mem_data_pointer_t);
+
+ -- -------------------------------------------------------------------------
+ --
+ -- Function Name: erase_mem
+ --
+ -- Description: erase_mem is used to perform memory data ERASE
+ -- operation above memory block or memory page region.
+ --
+ -- Routine is built-in addressing performance parameters.
+ -- Routine performs N successive erase operations.
+ -- For N successive erase operations instead of :
+ -- N x find + N x erase -->
+ -- erase_mem provides the posiibility of :
+ -- 1 x find + N x iterate + N x erase
+ -- Reducing the number of find element calls, operation
+ -- execution time is significantly affected.
+ --
+ -- [address_low, adress_high] must belong to the same
+ -- memory parition, handled by a single list.
+ --
+ -- Arguments:
+ --
+ -- IN Type Description
+ -- address_low integer Starting address of the memory
+ -- region to be erased.
+ -- address_high integer The last address of the memory
+ -- region to be erased.
+ --
+ -- INOUT
+ -- linked_list mem_data_pointer_t Linked list holding memory region
+ -- to be erased.
+ --
+ -- OUT
+ -- none
+ --
+ -- Returns
+ -- none
+ --
+ -- -------------------------------------------------------------------------
+ PROCEDURE erase_mem(
+ address_low : IN INTEGER;
+ address_high : IN INTEGER;
+ linked_list : INOUT mem_data_pointer_t);
+
+ -- ------------------------------------------------------------------------
+ --
+ -- Function Name: read_mem
+ --
+ -- Description: Memory READ operation performed above dynamically
+ -- allocated space.
+ --
+ -- Iterates through a linked list data structure holding
+ -- memory data. Performs a search for an address match.
+ --
+ -- If matched successfully, data kept by a linked list
+ -- element will be returned.
+ --
+ -- In case no match occurred, no allocation has been
+ -- performed for the search address.
+ -- Memory data is never written, set to initial value.
+ -- Initial data value returned.
+ --
+ -- Arguments:
+ --
+ -- IN Type Description
+ -- address integer Data address to be read.
+ --
+ -- INOUT
+ -- linked_list mem_data_pointer_t Linked list holding memory region
+ -- to be read. Depends on DUT
+ -- specific partition scheme.
+ -- data integer Read operation result.
+ --
+ -- OUT
+ -- none
+ --
+ -- Returns
+ -- none
+ --
+ -- -------------------------------------------------------------------------
+ PROCEDURE read_mem(
+ linked_list : INOUT mem_data_pointer_t;
+ data : INOUT INTEGER;
+ address : IN INTEGER);
+
+ -- -------------------------------------------------------------------------
+ --
+ -- Function Name: write_mem
+ --
+ -- Description: Memory WRITE operation performed above dynamically
+ -- allocated space.
+ --
+ -- Iterates through a linked list data structure holding
+ -- memory data. Performs a search for an address match.
+ --
+ -- If matched successfully, data kept by a linked list
+ -- element will be aligned with data argument value.
+ --
+ -- In case no match occurred, no allocation has been
+ -- performed for the search address.
+ -- Memory space for a new element is allocated, linked
+ -- into a list and set to data argument value.
+ --
+ -- If data argument value is recognized as initial,
+ -- memory space will be de-allocated for the addressed
+ -- location.
+ --
+ -- Arguments:
+ --
+ -- IN Type Description
+ -- address integer Address to be written.
+ -- data integer Data to be written.
+ --
+ -- INOUT
+ -- linked_list mem_data_pointer_t Linked list holding memory region
+ -- to be written. Depends on DUT
+ -- specific partition scheme.
+ --
+ -- OUT
+ -- none
+ --
+ -- Returns
+ -- none
+ --
+ -- -------------------------------------------------------------------------
+ PROCEDURE write_mem(
+ linked_list : INOUT mem_data_pointer_t;
+ address : IN INTEGER;
+ data : IN INTEGER);
+
+END PACKAGE memory;
+
+PACKAGE BODY memory IS
+ -- -------------------------------------------------------------------------
+ -- Override mechanism provided for default parameter values
+ -- -------------------------------------------------------------------------
+ PROCEDURE configure_memory(
+ max_data_c : IN INTEGER) IS
+ BEGIN
+ max_data := max_data_c;
+ END PROCEDURE configure_memory;
+
+ -- -------------------------------------------------------------------------
+ -- Create linked listed
+ -- -------------------------------------------------------------------------
+ PROCEDURE create_list(
+ key_address : IN INTEGER;
+ val_data : IN INTEGER;
+ root : INOUT mem_data_pointer_t) IS
+ BEGIN
+ root := NEW mem_data_t;
+ root.successor := NULL;
+ root.key_address := key_address;
+ root.val_data := val_data;
+ END PROCEDURE create_list;
+
+ -- -------------------------------------------------------------------------
+ -- Iterate through linked listed comapring key values
+ -- Stop when key value greater or equal
+ -- -------------------------------------------------------------------------
+ PROCEDURE position_list(
+ key_address : IN INTEGER;
+ root : INOUT mem_data_pointer_t;
+ found : INOUT mem_data_pointer_t;
+ prev : INOUT mem_data_pointer_t) IS
+ BEGIN
+ found := root;
+ prev := NULL;
+ -- Changed thanks to Sergey Selyutin
+ -- WHILE ((found /= NULL) AND (found.key_address < key_address)) LOOP
+ WHILE found /= NULL LOOP
+ IF (found.key_address >= key_address) THEN
+ EXIT;
+ END IF;
+ prev := found;
+ found := found.successor;
+ END LOOP;
+ END PROCEDURE position_list;
+
+ -- -------------------------------------------------------------------------
+ -- Add new element to a linked list
+ -- -------------------------------------------------------------------------
+ PROCEDURE insert_list(
+ key_address : IN INTEGER;
+ val_data : IN INTEGER;
+ root : INOUT mem_data_pointer_t) IS
+
+ VARIABLE new_element : mem_data_pointer_t;
+ VARIABLE found : mem_data_pointer_t;
+ VARIABLE prev : mem_data_pointer_t;
+ BEGIN
+ position_list(key_address, root, found, prev);
+
+ -- Insert at list tail
+ IF (found = NULL) THEN
+ prev.successor := NEW mem_data_t;
+ prev.successor.key_address := key_address;
+ prev.successor.val_data := val_data;
+ prev.successor.successor := NULL;
+ ELSE
+ -- Element exists, update memory data value
+ IF (found.key_address = key_address) THEN
+ found.val_data := val_data;
+ ELSE
+ -- No element found, allocate and link
+ new_element := NEW mem_data_t;
+ new_element.key_address := key_address;
+ new_element.val_data := val_data;
+ new_element.successor := found;
+ -- Possible root position
+ IF (prev /= NULL) THEN
+ prev.successor := new_element;
+ ELSE
+ root := new_element;
+ END IF;
+ END IF;
+ END IF;
+ END PROCEDURE insert_list;
+
+ -- -------------------------------------------------------------------------
+ -- Remove element from a linked list
+ -- -------------------------------------------------------------------------
+ PROCEDURE remove_list(
+ key_address : IN INTEGER;
+ root : INOUT mem_data_pointer_t) IS
+
+ VARIABLE found : mem_data_pointer_t;
+ VARIABLE prev : mem_data_pointer_t;
+ BEGIN
+ position_list(key_address, root, found, prev);
+ IF (found /= NULL) THEN
+ -- Key value match
+ IF (found.key_address = key_address) THEN
+ -- Handle root position removal
+ IF (prev /= NULL) THEN
+ prev.successor := found.successor;
+ ELSE
+ root := found.successor;
+ END IF;
+ DEALLOCATE(found);
+ END IF;
+ END IF;
+ END PROCEDURE remove_list;
+
+ -- -------------------------------------------------------------------------
+ -- Remove range of elements from a linked list
+ -- Higher performance than one-by-one removal
+ -- -------------------------------------------------------------------------
+ PROCEDURE remove_list_range(
+ address_low : IN INTEGER;
+ address_high : IN INTEGER;
+ root : INOUT mem_data_pointer_t) IS
+
+ VARIABLE iter : mem_data_pointer_t;
+ VARIABLE prev : mem_data_pointer_t;
+ VARIABLE link_element : mem_data_pointer_t;
+ BEGIN
+ iter := root;
+ prev := NULL;
+ -- Find first linked list element belonging to
+ -- a specified address range [address_low, address_high]
+ -- Changed thanks to Sergey Sulyutin
+ -- WHILE ((iter /= NULL) AND NOT (
+ -- (iter.key_address >= address_low) AND
+ -- (iter.key_address <= address_high))) LOOP
+ WHILE iter /= NULL LOOP
+ IF ((iter.key_address >= address_low) AND
+ (iter.key_address <= address_high)) THEN
+ EXIT;
+ END IF;
+ prev := iter;
+ iter := iter.successor;
+ END LOOP;
+ -- Continue until address_high reached
+ -- Deallocate linked list elements pointed by iterator
+ IF (iter /= NULL) THEN
+ -- Changed thanks to Sergey Sulyutin
+ -- WHILE ((iter /= NULL) AND
+ -- (iter.key_address >= address_low) AND
+ -- (iter.key_address <= address_high)) LOOP
+ WHILE iter /= NULL LOOP
+ IF ((iter.key_address < address_low) OR
+ (iter.key_address > address_high)) THEN
+ EXIT;
+ END IF;
+ link_element := iter.successor;
+ DEALLOCATE(iter);
+ iter := link_element;
+ END LOOP;
+ -- Handle possible root value change
+ IF prev /= NULL THEN
+ prev.successor := link_element;
+ ELSE
+ root := link_element;
+ END IF;
+ END IF;
+ END PROCEDURE remove_list_range;
+
+ -- -------------------------------------------------------------------------
+ -- Create side linked list modelling corrupted memory area
+ -- -------------------------------------------------------------------------
+ PROCEDURE create_list_range(
+ address_low : IN INTEGER;
+ address_high : IN INTEGER;
+ root : INOUT mem_data_pointer_t;
+ last : INOUT mem_data_pointer_t) IS
+
+ VARIABLE new_element : mem_data_pointer_t;
+ VARIABLE prev : mem_data_pointer_t;
+ BEGIN
+ create_list(address_low, -1, root);
+ prev := root;
+ -- Linked list representing memory region :
+ -- [address_low, address_high], memory data value corrupted
+ -- Heightens corrupt and erase operation performance
+ FOR I IN (address_low + 1) TO address_high LOOP
+ new_element := NEW mem_data_t;
+ new_element.key_address := I;
+ new_element.val_data := -1;
+ prev.successor := new_element;
+ prev := new_element;
+ END LOOP;
+ prev.successor := NULL;
+ last := prev;
+ END PROCEDURE create_list_range;
+
+ -- -------------------------------------------------------------------------
+ -- Merge corrupted with memory area
+ -- -------------------------------------------------------------------------
+ PROCEDURE insert_list_range(
+ root_dst : INOUT mem_data_pointer_t;
+ root_src : INOUT mem_data_pointer_t;
+ root_src_last : INOUT mem_data_pointer_t) IS
+
+ VARIABLE key : INTEGER;
+ VARIABLE found : mem_data_pointer_t;
+ VARIABLE prev : mem_data_pointer_t;
+ BEGIN
+ IF (root_dst /= NULL) THEN
+ key := root_src.key_address;
+ -- Insert side created corrupted memory region
+ -- into corresponding linked list
+ position_list(key, root_dst, found, prev);
+ IF (found = NULL) THEN
+ prev.successor := root_src;
+ ELSE
+ root_src_last.successor := found;
+ IF (prev /= NULL) THEN
+ prev.successor := root_src;
+ ELSE
+ root_dst := root_src;
+ END IF;
+ END IF;
+ ELSE
+ root_dst := root_src;
+ END IF;
+ END PROCEDURE insert_list_range;
+
+ -- -------------------------------------------------------------------------
+ -- Address range to be corrupted
+ -- -------------------------------------------------------------------------
+ PROCEDURE corrupt_mem(
+ address_low : IN INTEGER;
+ address_high : IN INTEGER;
+ linked_list : INOUT mem_data_pointer_t) IS
+
+ VARIABLE sub_linked_list : mem_data_pointer_t;
+ VARIABLE sub_linked_list_last : mem_data_pointer_t;
+ BEGIN
+ sub_linked_list := NULL;
+ sub_linked_list_last := NULL;
+ IF (linked_list /= NULL) THEN
+ remove_list_range(
+ address_low,
+ address_high,
+ linked_list
+ );
+ END IF;
+ create_list_range(
+ address_low,
+ address_high,
+ sub_linked_list,
+ sub_linked_list_last
+ );
+ insert_list_range(
+ linked_list,
+ sub_linked_list,
+ sub_linked_list_last
+ );
+ END PROCEDURE corrupt_mem;
+
+ -- -------------------------------------------------------------------------
+ -- Address range to be erased
+ -- -------------------------------------------------------------------------
+ PROCEDURE erase_mem(
+ address_low : IN INTEGER;
+ address_high : IN INTEGER;
+ linked_list : INOUT mem_data_pointer_t) IS
+
+ BEGIN
+ remove_list_range(
+ address_low,
+ address_high,
+ linked_list
+ );
+ END PROCEDURE erase_mem;
+
+ -- -------------------------------------------------------------------------
+ -- Memory READ operation performed above dynamically allocated space
+ -- -------------------------------------------------------------------------
+ PROCEDURE read_mem(
+ linked_list : INOUT mem_data_pointer_t;
+ data : INOUT INTEGER;
+ address : IN INTEGER) IS
+
+ VARIABLE found : mem_data_pointer_t;
+ VARIABLE prev : mem_data_pointer_t;
+ VARIABLE mem_data : INTEGER;
+ BEGIN
+ IF (linked_list = NULL) THEN
+ -- Not allocated, not written, initial value
+ mem_data := max_data ;
+ ELSE
+ position_list(address, linked_list, found, prev);
+ IF (found /= NULL) THEN
+ IF found.key_address = address THEN
+ -- Allocated, val_data stored
+ mem_data := found.val_data;
+ ELSE
+ -- Not allocated, not written, initial value
+ mem_data := max_data ;
+ END IF;
+ ELSE
+ -- Not allocated, not written, initial value
+ mem_data := max_data ;
+ END IF;
+ END IF;
+ data := mem_data;
+ END PROCEDURE read_mem;
+
+ -- -------------------------------------------------------------------------
+ -- Memory WRITE operation performed above dynamically allocated space
+ -- -------------------------------------------------------------------------
+ PROCEDURE write_mem(
+ linked_list : INOUT mem_data_pointer_t;
+ address : IN INTEGER;
+ data : IN INTEGER) IS
+
+ BEGIN
+ IF (data /= max_data ) THEN
+ -- Handle possible root value update
+ IF (linked_list /= NULL) THEN
+ insert_list(address, data, linked_list);
+ ELSE
+ create_list(address, data, linked_list);
+ END IF;
+ ELSE
+ -- Deallocate if initial value written
+ -- No linked list, NOP, initial value implicit
+ IF (linked_list /= NULL) THEN
+ remove_list(address, linked_list);
+ END IF;
+ END IF;
+ END PROCEDURE write_mem;
+
+END PACKAGE BODY memory;