| /* hp3000_mem.h: HP 3000 memory subsystem interface declarations | |
| Copyright (c) 2016, J. David Bryan | |
| Permission is hereby granted, free of charge, to any person obtaining a copy | |
| of this software and associated documentation files (the "Software"), to deal | |
| in the Software without restriction, including without limitation the rights | |
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
| copies of the Software, and to permit persons to whom the Software is | |
| furnished to do so, subject to the following conditions: | |
| The above copyright notice and this permission notice shall be included in | |
| all copies or substantial portions of the Software. | |
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
| AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | |
| ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |
| WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
| Except as contained in this notice, the name of the author shall not be used | |
| in advertising or otherwise to promote the sale, use or other dealings in | |
| this Software without prior written authorization from the author. | |
| 10-Oct-16 JDB Created | |
| This file contains declarations used by the CPU, I/O Processor, Multiplexer | |
| Channel, and Selector Channel to interface with the HP 3000 memory subsystem. | |
| */ | |
| /* Debug flags. | |
| Implementation notes: | |
| 1. Memory debug flags are allocated in descending order, as they may be used | |
| by other modules (e.g., CPU) that allocate their own flags in ascending | |
| order. No check is made for overlapping values. | |
| */ | |
| #define DEB_MDATA (1u << 31) /* trace memory reads and writes */ | |
| #define DEB_MFETCH (1u << 30) /* trace memory instruction fetches */ | |
| #define DEB_MOPND (1u << 29) /* trace memory operand accesses */ | |
| /* Architectural constants. | |
| The type used to represent a main memory word value is defined. An array of | |
| this type is used to simulate the CPU main memory. | |
| Implementation notes: | |
| 1. The MEMORY_WORD type is a 16-bit unsigned type, corresponding with the | |
| 16-bit main memory in the HP 3000. Unlike the general data type, which | |
| is a 32-bit type for speed, main memory does not benefit from the faster | |
| 32-bit execution on IA-32 processors, as only one instruction in the | |
| cpu_read_memory and cpu_write_memory routines has an operand override | |
| that invokes the slower instruction fetch path. There is a negligible | |
| difference in the Memory Pattern Test diagnostic execution speeds for the | |
| uint32 vs. uint16 definition, whereas the VM requirements are doubled for | |
| the former. | |
| */ | |
| typedef uint16 MEMORY_WORD; /* HP 16-bit memory word representation */ | |
| /* Byte accessors. | |
| The HP 3000 is a word-addressable machine. Byte addressing is implemented by | |
| assuming that a memory of N physical words may be addressed as 2N bytes. The | |
| "byte-capable" machine instructions use "relative byte addresses" that are | |
| used to obtain absolute word addresses by dividing by two and then accessing | |
| the upper or lower byte of the resulting word, depending on the LSB of the | |
| byte address. | |
| In simulation, this module provides a byte access structure and a set of | |
| routines that read or write the next byte in ascending byte-offset order. | |
| The structure is initialized with the starting byte offset from a specified | |
| base register value and then is passed as a parameter to the other routines, | |
| which update the fields accordingly for the access requested. This relieves | |
| the caller from having to manage the continual logical-to-physical address | |
| translation, word buffering, byte selection, etc. | |
| Byte accessors are also used to provide debug traces of byte operands in | |
| memory. Initializing an accessor sets a field containing the absolute byte | |
| memory address; this address may be passed to the byte formatters to print | |
| the operand. | |
| In most cases, operands are defined by starting byte addresses and byte | |
| counts. However, some operands (e.g., EDIT instruction operands) are | |
| delineated only by the extents of the accesses. For these operands, byte | |
| accessors maintain the lowest byte addresses and offsets actually accessed, | |
| as well as the lengths of the extent of the accesses. | |
| */ | |
| typedef struct { /* byte access descriptor */ | |
| HP_WORD *byte_offset; /* relative byte offset of the next byte */ | |
| HP_WORD data_word; /* memory data word containing the current byte */ | |
| ACCESS_CLASS class; /* memory access classification */ | |
| uint32 word_address; /* logical word address containing the next byte */ | |
| t_bool write_needed; /* TRUE if the data word must be written to memory */ | |
| uint32 count; /* current count of bytes accessed */ | |
| uint32 length; /* (trace) length of extent of access */ | |
| uint32 initial_byte_address; /* (trace) initial absolute byte address */ | |
| uint32 initial_byte_offset; /* (trace) initial relative byte offset */ | |
| uint32 first_byte_address; /* (trace) lowest absolute byte address accessed */ | |
| uint32 first_byte_offset; /* (trace) lowest relative byte offset accessed */ | |
| } BYTE_ACCESS; | |
| /* Memory global SCP support routines */ | |
| t_stat mem_examine (t_value *eval_array, t_addr address, UNIT *uptr, int32 switches); | |
| t_stat mem_deposit (t_value value, t_addr address, UNIT *uptr, int32 switches); | |
| /* Global memory functions. | |
| mem_initialize : allocate main memory | |
| mem_is_empty : check for a non-zero value within a range of memory locations | |
| mem_fill : set all memory locations to a specified value | |
| mem_read : read a word from main memory | |
| mem_write : write a word to main memory | |
| mem_init_byte : initialize a memory byte access structure | |
| mem_set_byte : set the access structure to a new byte offset | |
| mem_lookup_byte : return a byte at a specified index in a table | |
| mem_read_byte : read the next byte from memory | |
| mem_write_byte : write the next byte to memory | |
| mem_modify_byte : replace the last byte written to memory | |
| mem_post_byte : post the word containing the last byte modified in place to memory | |
| mem_update_byte : rewrite the word containing the last byte written to memory | |
| fmt_byte_operand : format a byte operand in memory into a character string | |
| fmt_bcd_operand : format a BCD operand in memory into a character string | |
| */ | |
| extern t_bool mem_initialize (uint32 memory_size); | |
| extern t_bool mem_is_empty (uint32 starting_address); | |
| extern void mem_fill (uint32 starting_address, HP_WORD fill_value); | |
| extern t_bool mem_read (DEVICE *dptr, ACCESS_CLASS classification, uint32 offset, HP_WORD *value); | |
| extern t_bool mem_write (DEVICE *dptr, ACCESS_CLASS classification, uint32 offset, HP_WORD value); | |
| extern void mem_init_byte (BYTE_ACCESS *bap, ACCESS_CLASS class, HP_WORD *byte_offset, uint32 block_length); | |
| extern void mem_set_byte (BYTE_ACCESS *bap); | |
| extern uint8 mem_lookup_byte (BYTE_ACCESS *bap, uint8 index); | |
| extern uint8 mem_read_byte (BYTE_ACCESS *bap); | |
| extern void mem_write_byte (BYTE_ACCESS *bap, uint8 byte); | |
| extern void mem_modify_byte (BYTE_ACCESS *bap, uint8 byte); | |
| extern void mem_post_byte (BYTE_ACCESS *bap); | |
| extern void mem_update_byte (BYTE_ACCESS *bap); | |
| extern char *fmt_byte_operand (uint32 byte_address, uint32 byte_count); | |
| extern char *fmt_translated_byte_operand (uint32 byte_address, uint32 byte_count, uint32 table_address); | |
| extern char *fmt_bcd_operand (uint32 byte_address, uint32 digit_count); |