comp.lang.ada
 help / color / mirror / Atom feed
From: Niklas Holsti <niklas.holsti@tidorum.invalid>
Subject: Re: Creating several types from a base type and conversion
Date: Sat, 18 Jan 2020 19:57:06 +0200
Date: 2020-01-18T19:57:06+02:00	[thread overview]
Message-ID: <h8gv7iFfs9pU1@mid.individual.net> (raw)
In-Reply-To: <f531cd40-6734-46cb-967e-638cf1004426@googlegroups.com>

On 2020-01-18 9:32, Ken Roberts wrote:
> New to ada with a question about types.

Welcome to the language!

What did you program in before? Sometimes it is easier to give advice if 
one knows the background of the person asking for it.

> The theory is creating an old computer emulator. Memory is an array
> of BaseWord's (Older computer had 32K of memory, so making an array
> on a modern computer is peanuts).

Yes, but note that in some Ada compilers, the predefined Integer is only 
16 bits, so some memory address computations (offsets) in a 32K range 
might overflow... better define your own "memory address" type with the 
computational range you need (which may be more than 32K, or should 
perhaps use modular arithmetic).

> Creating a base type that is stored into the memory array
> 
> <code>
> 
>      type BaseWord is array (00 .. 29) of Boolean;
>      pragma pack (BaseWord);
> 
> </code>

Note that such a definition does not ensure that the Boolean with index 
0 is the least significant bit, or the most significant bit -- different 
compilers can use different conventions. And there is no way in current 
Ada to specify the indexing order.

I think the first thing you should consider, and decide, is whether you 
want your emulator to be fully portable to all standard Ada 
implementations, or to the commonly available Ada compilers. The main 
issues are the endianness and the word length of the computer you want 
to emulate:

- Can the computer to be emulated address only full 30-bit words, or can 
it address also, say, characters (bytes) within a word?

- Is the computer you intend to emulate big-endian or little-endian? 
There are two aspects to this question: first, conventions for numbering 
bits (is bit 0 most significant or least significant?) and second, 
addressing sub-word-units like characters (if possible) within a word 
(does the lowest sub-word address access the most significant end of the 
addressed word, or the least-significant end?).

I'll sketch an approach that applies to the commonly available Ada 
compilers and makes no a-priori assumptions on the endianness of the 
computer to be emulated.

I recommend starting from the type Interfaces.Unsigned_32. This is a 
32-bit, unsigned, modular integer type, and has predefined shift and 
rotate operations as well as bit-wise Boolean operations. The type is 
not required to exist in all Ada compilers (for example, the computer 
you are emulating would probably instead have had a type 
Interfaces.Unsigned_30) but does exist in GNAT and other Ada compilers 
for most modern computers which tend to have 32-bit machine integers.

The 30-bit unsigned integer type is then

    subtype Base_Word is Interfaces.Unsigned_32 range 0 .. 2**30 - 1;

and the emulated memory is an array of 2**15 Base_Word elements, indexed 
by the memory-address type.

Note that Base_Word does not wrap around at 30 bits (as the type "mod 
2**30" would) but at 32 bits. But you can emulate 30-bit wrap-around by 
clearing the two high bits after every arithmetic operation.

I would then define a function to extract any desired bit-field from a 
Base_Word, for example

    function Field (Word : Base_Word; Low_Bit, High_Bit : Bit_Number)
    return Base_Word

where Bit_Number is range 0 .. 29.

The easiest way to implement such a function is by the left-shift and 
right-shift operations for Base_Word. In this implementation, you can 
decide if you want Bit_Number to work in a little-endian or big-endian way.

I would also define a procedure Set_Field similarly:

    procedure Set_Field (
       Word              : in out Base_Word;
       Low_Bit, High_Bit : in     Bit_Number;
       New_Value         : in     Base_Word);

Again, this can be done with the shift operations (or rotate operations) 
and some Boolean operations on Base_Word.

If the computer to be emulated can access sub-word data, for example 
bytes with a byte address, you can now use the above subprograms to 
implement operations to read or write such sub-word data, and again you 
can implement either little-endian sub-word order or big-endian sub-word 
order.

These tools should let you decode instructions and their bit-fields and 
emulate all "logical" (Boolean) instructions and load/store instructions.

If you prefer to implement the bit-field lay-outs of instruction words 
by means of record representation clauses, that is fine too. However, 
note that the endianness of the bit numbering in such clauses may be 
different in different Ada compilers, so you should also use the 
Bit_Order aspect, together with the representation clause, to define the 
order you want to use (which is probably the same as in the 
instruction-set manuals for the emulated computer). Also, you then have 
to use Unchecked_Conversion to convert between Base_Word and the 
instruction record types, but that is good and safe as long as you have 
taken care of the bit order.

For the arithmetic instructions, you must of course first consider how 
the emulated computer represents negative numbers: two's complement, 
one's complement, or sign-magnitude?

The answer will tell you how to convert, using ordinary type conversions 
and ordinary arithmetic (not Unchecked_Conversion) from Base_Word to the 
corresponding signed type (for use as an operand in the emulation of an 
arithmetic instruction) and from the signed type (as the result of the 
arithmetic instruction) back to Base_Type for storing in an emulated 
register or in the emulated memory.

Remember that you may have to use wider types for the results of 
arithmetic operations so as to handle and detect overflows. Unsigned_32 
already gives you two more high-end bits, so it can be used for addition 
and subtraction, but for multiplication you may want to use a 64-bit 
type, for example.

(I agree with others that there are some errors in the declarations you 
gave (elided here) which should have made GNAT reject the code.)
  > For most stuff, memory will be returning either DataWord or
> InstructionWord for each memory access, but I'm also looking at an 
> easier way to manage characters for text display on the emulated 
> monitors.
I would assume that in the original system, the diplay of characters on 
the monitors was implemented in the SW programs that ran on the emulated 
processor. Why should the processor emulator do something special for 
this? Did the monitors display data directly from "display buffers" in 
the 32K memory, using DMA?

-- 
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
       .      @       .

  parent reply	other threads:[~2020-01-18 17:57 UTC|newest]

Thread overview: 49+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-01-18  7:32 Creating several types from a base type and conversion Ken Roberts
2020-01-18 12:16 ` Simon Wright
2020-01-18 12:49   ` Ken Roberts
2020-01-18 14:56     ` Bill Findlay
2020-01-18 16:13       ` Jeffrey R. Carter
2020-01-18 18:20         ` Bill Findlay
2020-01-18 18:32           ` Jeffrey R. Carter
2020-01-18 20:34             ` Simon Wright
2020-01-20 16:38               ` Bill Findlay
2020-01-18 22:20       ` Ken Roberts
2020-01-18 15:09     ` Simon Wright
2020-01-18 22:16       ` Ken Roberts
2020-01-18 22:35         ` Simon Wright
2020-01-18 23:03           ` Ken Roberts
2020-01-18 23:38             ` Simon Wright
2020-01-19  0:12               ` Ken Roberts
2020-01-19  9:37                 ` Simon Wright
2020-01-19 11:48                   ` AdaMagica
2020-01-19 14:51                     ` Simon Wright
2020-01-19 15:24                       ` Niklas Holsti
2020-01-19 16:11                     ` Optikos
2020-01-19  0:33               ` Ken Roberts
2020-01-19  0:07         ` Niklas Holsti
2020-01-18 15:47     ` Simon Wright
2020-01-21 21:35     ` Shark8
2020-01-21 23:06       ` Niklas Holsti
2020-01-22  1:08         ` Ken Roberts
2020-01-22 14:18           ` Ken Roberts
2020-01-22  8:37       ` Simon Wright
2020-01-22 14:32         ` Shark8
2020-01-22 15:40           ` Simon Wright
2020-01-18 14:17   ` Optikos
2020-01-18 17:57 ` Niklas Holsti [this message]
2020-01-18 22:59   ` Ken Roberts
2020-01-19  0:30     ` Niklas Holsti
2020-01-19  1:07       ` Ken Roberts
2020-01-19  3:37 ` Ken Roberts
2020-01-23 21:39 ` Optikos
2020-01-24  9:35   ` Ken Roberts
2020-01-24 10:04     ` AdaMagica
2020-01-24 12:38     ` Optikos
2020-01-24 15:01       ` Ken Roberts
2020-01-24 15:22         ` Simon Wright
2020-01-24 15:40           ` Ken Roberts
2020-01-24 15:54   ` Simon Wright
2020-01-25 10:37 ` Ken Roberts
2020-01-25 10:44   ` Ken Roberts
2020-01-25 20:26   ` Shark8
2020-01-27 14:10 ` Ken Roberts
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox