comp.lang.ada
 help / color / mirror / Atom feed
From: Ken Roberts <alisonken1@gmail.com>
Subject: Re: Creating several types from a base type and conversion
Date: Sat, 25 Jan 2020 02:37:15 -0800 (PST)
Date: 2020-01-25T02:37:15-08:00	[thread overview]
Message-ID: <01f6b6cc-9ce6-43b8-9c67-5595fa960381@googlegroups.com> (raw)
In-Reply-To: <f531cd40-6734-46cb-967e-638cf1004426@googlegroups.com>

It might be that I can only really concentrate on learning Ada on my weekends (thursday night -> saturday) subject to $HoneyDoList.

Needless to say, I'm not always the brightest nowadays between age and free time without some extra help, so sorry for seeming a little dense right now.

Here's the computer representation as expressed in documentation and how I'm used to working on the hardware:

30-bit words (both memory storage and hardware registers)

Bit Number : 29 28 .. 01 00
MSBit on left, LSBit on right

30-bit words using half-word (memory access only)

Bit number:  29 28 .. 16 15 14 13 .. 01 00
Half word : |    Upper     |    Lower     |

Instruction format:

Bit number: | 29 .. 24 | 23 .. 21 | 20 .. 18 | 17 .. 15 | 14 .. 0 |
Field     : | Op code  |    J     |    K     |    B     |    Y    |

Op code : Instruction
j       : Skip next instruction modification
k       : Source or destination of data
b       : Index register to use to modify Y
y       : Constant or memory address


Sample program 1 (all numbering is octal notation):

<code>

| Address | Contents    | Description
| 00600   | 12130 00601 | f = 12  : Opcode (Load A register)
|         |             | j = 1   : 1 = always skip next instruction
|         |             | k = 3   : y is memory address, 30 bits
|         |             | y = 601 : Data
| 00601   | 00005 00001 | Data
|         |             | A register initial: 00005 00001
| 00602   | 06000 00017 | f = 06  : Opcode (Shift A left circular)
|         |             | j = 0   : Execute next instruction
|         |             | k = 0   : Shift count is y
|         |             | y = 17  : Data (17 octal, 15 decimal)
|         |             | A register final: 00001 00005

</code>

Sample program using 60-bit register instruction:

60-bit register
Bit number     : | 59 .. 30 | 29 .. 00 |
Registers used : | A reg    | Q reg    |

<code>

| Address | Contents    | Description
| 00600   | 10000 00001 | Load Q register
|         |             | Q register = 00000 00001
| 00601   | 11000 00005 | Load A register
|         |             | A register = 00000 00005
| 00602   | 07000 00036 | Left shift AQ register circular
|         |             | Shift count (36 octal, 30 decimal)
|         |             |
|         |             | AQ initial : 00000 00005 00000 00001
|         |             | A register initial = 00000 00005
|         |             | Q register initial = 00000 00001
|         |             |
|         |             | AQ final   : 00000 00001 00000 00005
|         |             | A register final = 00000 00001
|         |             | Q register final = 00000 00005

</code>

My programming environment is:

Intel-based system
64-bit Fedora based KDE desktop system
Fedora repository has the GNAT compiler suite (GCC Ada - AdaCore?)

With these considerations in mind, I'm trying to figure out the best way to represent the computer hardware (register and memory).

The register and memory base word would be a 30-bit quantity (Interfaces.unsigned_32 possibly?) with 2**30 bit limit, so all register/memory representations would be easily convertible.

Memory representation will be an array (0 .. #8#77777# or 32,768 words) of 30-bit words.

The 60-bit instructions (there's only 2 shift instructions, multiply, which puts answer in QA register(s)) and divide, which uses combined QA register for data, and puts answer in Q and remainder in A))

Based on Niklas Holsti's recommendation, it looks like the following would be what I want to do:

<code>

package core is

with Interfaces;

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

subtype D_Word is Interfaces.Unsigned_64 with record
    Ru : Word;
    Rl : Word;
end record

for D_Word use record
    Ru : at 0 use 59 .. 30;
    Rl : at 0 use 29 .. 0;
end record

-- NOTE: I_Word is basically read-only
--       The only use is to make it easier to break down Word into
--       the fields to interpret the instruction and will not change
--       during the instruction execution cycle

I_Word is Word with record
    -- Not sure how to define this part yet
    -- See below for breakdown of bits-to-fields
end record

for I_Word use record
    f : at 0 range 29 .. 24;
    j : at 0 range 23 .. 21;
    k : at 0 range 20 .. 18;
    b : at 0 range 17 .. 15;
    y : at 0 range 14 .. 00;
end record

end package core;

</code>

With the above representation, I can use a D_Word for shifting
and be able to ignore unused 32/64 bits in hardware

<code>

-- Circular left shift register
procedure shift_left_logical (R     : <> Word'Class, 
                              Count : in Integer) is
    private
        D : D_Word;

        -- NOTE: By putting the same contents into both Ru and Rl
        --       I don't have to worry about extra bits from Unsigned_32
        D.Ru := R;
        D.Rl := R;

        -- NOTE: Only bits 5 .. 0 are used, the rest are ignored
        -- Add option to limit actual shifting to mod 30 since anything
        -- over 30 would just wrap around again
        -- ex: Count == 31  is equivalent to Count == 1
        --     on a 30-bit register
        if Count > 8#77# then
           C : Integer (Count and 8#77#);
        else
           C : Integer (Count);
        end if Count;

    end private;

    begin
        D.Shift_Left(C);

        -- Set the register to new value
        R := D.Ru;

    end shift_left_logical;

</code>

For the double-register shift

<code>

-- Circular left shift double register
procedure double_shift_left_logical (R1 : <> Word'Class, 
                                     R2 : <> Word'Class,
                                     Count : in Integer) is
    private
        D1 : D_Word;
        D2 : D_Word;

        -- Normal register order so lower register bits go to upper register
        D1.Ru := R1;  -- A register
        D1.Rl := R2;  -- Q register

        -- Reverse the register order so high register bits go to low register
        D2.Ru := R2;  -- Q register
        D2.Rl := R1;  -- A register

        -- NOTE: Only bits 5 .. 0 are used, the rest are ignored
        -- Add option to limit actual shifting to mod 60 since anything
        -- over 60 would just wrap around again
        -- ex: Count == 61  is equivalent to Count == 1
        --     on a 60-bit register
        if Count > 8#77# then
           C : Integer (Count and 8#77#);
        else
           C : Integer (Count);
        end if Count;

    end private;

    begin
        D1.Shift_Left(C);  -- AQ register pair
        D2.Shift_Left(C);  -- QA register pair

        -- Set the registers to new values
        R1 := D1.Ru;  -- A register
        R2 := D2.Ru;  -- Q Register

    end shift_left_logical;

</code>

This is from my limited understanding so far.

Thanks for all of your help - I wish I could catch on a little quicker, but age and $DayJob (plus $HoneyDoList) make learning a new language a little challenging lately.


  parent reply	other threads:[~2020-01-25 10:37 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
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 [this message]
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