From 6c56d89c8db4830418bdd27d5c775a77d0ab462b Mon Sep 17 00:00:00 2001 From: Trygve Laugstøl Date: Sun, 10 Feb 2013 16:26:03 +0100 Subject: wip --- vhdl/fmf/memory.vhd | 714 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 714 insertions(+) create mode 100644 vhdl/fmf/memory.vhd (limited to 'vhdl/fmf/memory.vhd') 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; -- cgit v1.2.3