1
0
mirror of https://github.com/simh/simh.git synced 2026-02-26 16:54:22 +00:00

FIO: Add generic pack/unpack buffer copy support

This commit is contained in:
Mark Pizzolato
2022-05-12 13:15:00 -07:00
parent 1a52d41154
commit 8016c6a0ad
2 changed files with 257 additions and 0 deletions

249
sim_fio.c
View File

@@ -52,6 +52,7 @@
sim_buf_copy_swapped - copy data swapping elements along the way
sim_buf_swap_data - swap data elements inplace in buffer if needed
sim_byte_swap_data - swap data elements inplace in buffer
sim_buf_pack_unpack - pack or unpack data between buffers
sim_shmem_open create or attach to a shared memory region
sim_shmem_close close a shared memory region
sim_chdir change working directory
@@ -91,6 +92,28 @@ t_bool sim_toffset_64; /* Large File (>2GB) file I/O Support availa
#define MIN(a,b) (((a) <= (b)) ? (a) : (b))
#endif
#define FIO_DBG_PACK 1 /* Pack/Unpack Test Detail */
static DEBTAB fio_debug[] = {
{"PACK", FIO_DBG_PACK, "Pack/Unpack Test Detail"},
{0}
};
static const char *sim_fio_test_description (DEVICE *dptr)
{
return "SCP FIO Testing";
}
static UNIT sim_fio_unit = { 0 };
static DEVICE sim_fio_test_dev = {
"SCP-FIO", &sim_fio_unit, NULL, NULL,
1, 0, 0, 0, 0, 0,
NULL, NULL, NULL, NULL, NULL, NULL,
NULL, DEV_NOSAVE|DEV_DEBUG, 0,
fio_debug, NULL, NULL, NULL, NULL, NULL,
sim_fio_test_description};
/* OS-independent, endian independent binary I/O package
For consistency, all binary data read and written by the simulator
@@ -177,6 +200,60 @@ for (j = 0; j < count; j++) { /* loop on items */
}
}
static uint32 _bit_index (uint32 bit, uint32 bits, t_bool LSB)
{
uint32 base, offset;
if (LSB)
return bit;
//return (bits * (bit / bits)) + bits - ((bit % bits) + 1); /* Reverse bit ordering - likely not useful */
base = (bits * (bit / bits)) - (((bits % 8) == 0) ? 8 : 0);
offset = ((base / bits) * (bits % 8));
bit = (bit % bits) + offset;
return base + (bits - (((bit + (bits % 8)) / 8) * 8) - (bits % 8)) + offset + ((bit + (bits % 8)) % 8);
}
t_bool sim_buf_pack_unpack (const void *sptr, /* source buffer pointer */
void *dptr, /* destination buffer pointer */
uint32 sbits, /* source buffer element size in bits */
t_bool sLSB_o_numbering, /* source numbered using LSB ordering */
uint32 scount, /* count of source elements */
uint32 dbits, /* interesting bits of each destination element */
t_bool dLSB_o_numbering) /* destination numbered using LSB ordering */
{
const uint8 *s = (const uint8 *)sptr;
uint8 *d = (uint8 *)dptr;
uint32 bits_to_process; /* bits in current source element remaining to be processed */
uint32 sbit_offset, dbit_offset;/* source and destination bit offsets */
uint32 sx; /* source byte index */
uint32 dx; /* destination byte index */
uint32 bit; /* Current Bit number */
uint32 element; /* Current element number */
sim_debug (FIO_DBG_PACK, &sim_fio_test_dev, "sim_buf_pack_unpack(sbits=%d, dLSB_o=%s, scount=%d, dbits=%d, dLSB_o=%s)\n", sbits, sLSB_o_numbering ? "True" : "False", scount, dbits, dLSB_o_numbering ? "True" : "False");
if (((dbits * scount) & 7) != 0)
return TRUE; /* Error - Can't process all source elements */
memset (d, 0, (dbits * scount) >> 3);
if (((sbits % 8) == 0) &&
(sbits == dbits) &&
(sLSB_o_numbering == dLSB_o_numbering)) {
sim_buf_copy_swapped (dptr, sptr, sbits >> 3, scount);
return FALSE;
}
bits_to_process = MIN (sbits, dbits);
for (element = 0; element < scount; element++) {
sbit_offset = element * sbits;
dbit_offset = element * dbits;
for (bit = 0; bit < bits_to_process; bit++, sbit_offset++, dbit_offset++) {
sx = _bit_index (sbit_offset, sbits, sLSB_o_numbering);
dx = _bit_index (dbit_offset, dbits, dLSB_o_numbering);
d[dx >> 3] |= (((s[sx >> 3] >> (sx & 7)) & 1) << (dx & 7));
}
}
return FALSE;
}
size_t sim_fwrite (const void *bptr, size_t size, size_t count, FILE *fptr)
{
size_t c, nelem, nbuf, lcnt, total;
@@ -308,6 +385,178 @@ free (without_quotes);
return dest;
}
/*
* DBD9 packing/encoding is:
* 9 character per pair of 36 bit words.
*
* 36b Bit numbers using bit
* word standard bit numbering byte offset
* 0 - 35 34 33 32 31 30 29 28 0 0
* 0 - 27 26 25 24 23 22 21 20 1 8
* 0 - 19 18 17 16 15 14 13 12 2 16
* 0 - 11 10 9 8 7 6 5 4 3 24
* 0 - 3 2 1 0 35 34 33 32 4 32
* 1 - 31 30 29 28 27 26 25 24 5 40
* 1 - 23 22 21 20 19 18 17 16 6 48
* 1 - 15 14 13 12 11 10 9 8 7 56
* 1 - 7 6 5 4 3 2 1 0 8 64
*
* word Bit numbers using PDP10 bit numbering
* 0 - B0 1 2 3 4 5 6 7
* 0 - 8 9 10 11 12 13 14 15
* 0 - 16 17 18 19 20 21 22 23
* 0 - 24 25 26 27 28 29 30 31
* 0 - 32 33 34 35 B0 1 2 3
* 1 - 4 5 6 7 8 9 10 11
* 1 - 12 13 14 15 16 17 18 19
* 1 - 20 21 22 23 24 25 26 27
* 1 - 28 29 30 31 32 33 34 35
*
* DLD9 packing/encoding is:
* 9 character per pair of 36 bit words.
*
* 36b Bit numbers using bit
* word standard bit numbering byte offset
* 0 - 7 6 5 4 3 2 1 0 0 0
* 0 - 15 14 13 12 11 10 9 8 1 8
* 0 - 23 22 21 20 19 18 17 16 2 16
* 0 - 31 30 29 28 27 26 25 24 3 24
* 0 - 3 2 1 0 35 34 33 32 4 32
* 1 - 11 10 9 8 7 6 5 4 5 40
* 1 - 19 18 17 16 15 14 13 12 6 48
* 1 - 27 26 25 24 23 22 21 20 7 56
* 1 - 35 34 33 32 31 30 29 28 8 64
*
* word Bit numbers using PDP10 bit numbering
* 0 - 28 29 30 31 32 33 34 35
* 0 - 20 21 22 23 24 25 26 27
* 0 - 12 13 14 15 16 17 18 19
* 0 - 4 5 6 7 8 9 10 11
* 0 - 32 33 34 35 B0 1 2 3
* 1 - 24 25 26 27 28 29 30 31
* 1 - 16 17 18 19 20 21 22 23
* 1 - 8 9 10 11 12 13 14 15
* 1 - B0 1 2 3 4 5 6 7
*/
uint32 int32_data[] = { 0x00000000, 0x00000001, 0x00000002, 0x00000003,
0x00000004, 0x00000005, 0x00000006, 0x00000007,
0x00000008, 0x00000009, 0x0000000A, 0x0000000B,
0x0000000C, 0x0000000D, 0x0000000E, 0x0000000F};
uint32 res_32bitM[] = { 0x00000000, 0x01000000, 0x02000000, 0x03000000,
0x04000000, 0x05000000, 0x06000000, 0x07000000,
0x08000000, 0x09000000, 0x0A000000, 0x0B000000,
0x0C000000, 0x0D000000, 0x0E000000, 0x0F000000};
uint32 res_32_1[] = { 0, 1, 0, 1,
0, 1, 0, 1,
0, 1, 0, 1,
0, 1, 0, 1};
uint16 int16_data[] = { 0x1234, 0x5678,
0x9ABC, 0xDEF0};
uint16 res_16bit[] = { 0x3412, 0x7856,
0xBC9A, 0xF0DE};
uint8 res_8bit[] = { 0, 1, 2, 3,
4, 5, 6, 7,
8, 9, 10, 11,
12, 13, 14, 15};
uint8 res_4bit[] = { 0x10, 0x32, 0x54, 0x76,
0x98, 0xba, 0xdc, 0xfe};
uint8 res_2bit[] = { 0xE4, 0xE4, 0xE4, 0xE4};
uint8 res_1bit[] = { 0xAA, 0xAA};
#if defined (USE_INT64)
t_uint64 int64_data[] = { 0x876543210, 0x012345678, 0x987654321, 0x123456789};
uint8 res_36bit[] = {0x10, 0x32, 0x54, 0x76, 0x88, 0x67, 0x45, 0x23, 0x01,
0x21, 0x43, 0x65, 0x87, 0x99, 0x78, 0x56, 0x34, 0x12};
uint8 res_36bitM[]= {0x87, 0x65, 0x43, 0x21, 0x00, 0x12, 0x34, 0x56, 0x78,
0x98, 0x76, 0x54, 0x32, 0x11, 0x23, 0x45, 0x67, 0x89};
uint8 int64_data_dbd9[18];
uint8 int64_data_dld9[18];
#endif
static struct pack_test {
const void *src;
const void *exp_dst;
uint32 sbits;
t_bool slsb;
uint32 dbits;
t_bool dlsb;
uint32 scount;
t_bool exp_stat;
} p_test[] =
{
#if defined (USE_INT64)
{&int64_data, &res_36bitM, 64, TRUE, 36, FALSE, 4, FALSE},
{&res_36bitM, &int64_data, 36, FALSE, 64, TRUE, 4, FALSE},
{&int64_data, &res_36bit, 64, TRUE, 36, TRUE, 4, FALSE},
{&res_36bit, &int64_data, 36, TRUE, 64, TRUE, 4, FALSE},
#endif
{&int16_data, &res_16bit, 16, TRUE, 16, FALSE, 4, FALSE},
{&int16_data, &res_16bit, 16, FALSE, 16, TRUE, 4, FALSE},
{&int16_data, &int16_data, 16, TRUE, 16, TRUE, 4, FALSE},
{&int16_data, &int16_data, 16, FALSE, 16, FALSE, 4, FALSE},
{&int32_data, &int32_data, 32, FALSE, 32, FALSE,16, FALSE},
{&int32_data, &int32_data, 32, TRUE, 32, TRUE, 16, FALSE},
{&int32_data, &res_32bitM, 32, TRUE, 32, FALSE,16, FALSE},
{&res_32bitM, &int32_data, 32, FALSE, 32, TRUE, 16, FALSE},
{&res_8bit, &res_8bit, 8, TRUE, 8, FALSE,16, FALSE},
{&res_8bit, &res_8bit, 8, FALSE, 8, TRUE, 16, FALSE},
{&res_8bit, &res_8bit, 8, FALSE, 8, FALSE,16, FALSE},
{&res_8bit, &res_8bit, 8, TRUE, 8, TRUE, 16, FALSE},
{&res_8bit, &res_8bit, 16, TRUE, 16, TRUE, 8, FALSE},
{&res_8bit, &res_8bit, 16, FALSE, 16, FALSE, 8, FALSE},
{&res_1bit, &res_32_1, 1, TRUE, 32, TRUE, 16, FALSE},
{&res_8bit, &int32_data, 8, TRUE, 32, TRUE, 2, FALSE},
{&res_4bit, &int32_data, 4, TRUE, 32, TRUE, 16, FALSE},
{&int32_data, &res_8bit, 32, TRUE, 8, TRUE, 16, FALSE},
{&int32_data, &int32_data, 32, TRUE, 32, TRUE, 16, FALSE},
{&int32_data, &int32_data, 16, TRUE, 16, TRUE, 32, FALSE},
{&int32_data, &int32_data, 8, TRUE, 8, TRUE, 64, FALSE},
{&int32_data, &res_8bit, 32, TRUE, 8, TRUE, 16, FALSE},
{&int32_data, &res_4bit, 32, TRUE, 4, TRUE, 16, FALSE},
{&int32_data, &res_2bit, 32, TRUE, 2, TRUE, 16, FALSE},
{&int32_data, &res_1bit, 32, TRUE, 1, TRUE, 16, FALSE},
{NULL},
};
t_stat sim_fio_test (const char *cptr)
{
struct pack_test *pt;
t_stat r = SCPE_OK;
char test_desc[128];
uint8 result[128];
sim_register_internal_device (&sim_fio_test_dev);
sim_fio_test_dev.dctrl = (sim_switches & SWMASK ('D')) ? FIO_DBG_PACK : 0;
sim_set_deb_switches (SWMASK ('F'));
sim_messagef (SCPE_OK, "sim_buf_pack_unpack - tests\n");
for (pt = p_test; pt->src; ++pt) {
t_bool res;
snprintf (test_desc, sizeof (test_desc), "%dbit%s->%dbit%s %d words", pt->sbits, pt->slsb ? "LSB" : "MSB", pt->dbits, pt->dlsb ? "LSB" : "MSB", pt->scount);
memset (result, 0x80, sizeof (result));
res = sim_buf_pack_unpack (pt->src, result, pt->sbits, pt->slsb, pt->scount, pt->dbits, pt->dlsb);
if (res == pt->exp_stat) {
if (!res) {
if (0 == memcmp (pt->exp_dst, result, (pt->scount * pt->dbits) / 8))
sim_messagef (SCPE_OK, "%s - GOOD\n", test_desc);
else {
uint32 i;
r = sim_messagef (SCPE_IERR, "%s - BAD Data:\n", test_desc);
sim_messagef (SCPE_IERR, "Off: Exp: Got:\n");
for (i = 0; i < ((pt->scount * pt->dbits) / 8); i++)
sim_messagef (SCPE_IERR, "%3d 0x%02X%s0x%02X\n", i, ((uint8 *)pt->exp_dst)[i], (((uint8 *)pt->exp_dst)[i] == result[i]) ? " " : " != ", result[i]);
}
}
}
else
r = sim_messagef (SCPE_IERR, "%s - BAD Status - Expected: %s got %s\n", test_desc, pt->exp_stat ? "True" : "False", res ? "True" : "False");
}
return r;
}
#if defined(_WIN32)
#include <direct.h>
#include <io.h>

View File

@@ -94,6 +94,14 @@ void sim_print_filelist (char **filelist);
void sim_buf_swap_data (void *bptr, size_t size, size_t count);
void sim_byte_swap_data (void *bptr, size_t size, size_t count);
void sim_buf_copy_swapped (void *dptr, const void *bptr, size_t size, size_t count);
t_bool sim_buf_pack_unpack (const void *sptr, /* source buffer pointer */
void *dptr, /* destination buffer pointer */
uint32 sbits, /* source buffer element size in bits */
t_bool sLSB_o_numbering, /* source numbered using LSB ordering */
uint32 scount, /* count of source elements */
uint32 dbits, /* interesting bits of each destination element */
t_bool dLSB_o_numbering); /* destination numbered using LSB ordering */
t_stat sim_fio_test (const char *cptr);
const char *sim_get_os_error_text (int error);
typedef struct SHMEM SHMEM;
t_stat sim_shmem_open (const char *name, size_t size, SHMEM **shmem, void **addr);