k2/cardslots [ Modules ]

[ Top ] [ Modules ]

NAME

      cardslots

FUNCTION

This module is intended to provide an abstraction of the virtual Kestrel-2 address space.

The vast majority of the time, you'll want to use these functions for accessing the Kestrel-2 memory space:

* slots_read_hword(), slots_write_hword()

              for reading and writing 16-bit values, and,

* slots_read_byte(), slots_write_byte()

              for reading and writing 8-bit values.

NOTE: Although the Kestrel-2EX's processor is a 64-bit processor, we only provide procedures for accessing 16-bit values. That's because a real hardware implementation will only have a 16-bit path to system RAM. The processor emulation module is responsible for breaking 32-bit and 64-bit accesses into smaller 16-bit chunks.

For the purposes of maintaining a GUI, there's a specialized function, slots_translate_address_from_virtual(), which helps provide efficient access to bitmap data for rendering to the screen. DO NOT call this function unless you know exactly what you're doing. It is easy to crash the application with it if you're not extra careful.

slots_init() is where you'll find the code that provides the initial virtual environment configuration. "Slots" (cardslot_t structures) are populated from what is believed to be the most frequently accessed resource to the least frequently accessed resource.


cardslots/cardslot_rd_fn, cardslots/cardslot_wr_fn [ Types ]

[ Top ] [ cardslots ] [ Types ]

NAME

      cardslot_rd_fn
      cardslot_wr_fn

SYNOPSIS

typedef void cardslot_rd_fn(
                void* data, privilege_t privilege,
                uint32_t addr, uint8_t lanes, 
                uint16_t* result, bool* error
                );

typedef void cardslot_wr_fn(
                void* data, privilege_t privilege,
                uint32_t addr, uint8_t lanes, uint16_t value,
                bool* error
                );

FUNCTION

tbd

Although these callbacks may be called from any thread context, as long as you use the slots_{read,write}_{byte,hword} functions to invoke them, there is no need to explicitly lock resources; this should be done for you automatically by the public API.

INPUTS

      data -- Resource-specific data (e.g., for memory resources, the base
              local address of a buffer large enough to hold all of the
              memory that resource provides).
      privilege -- What privilege the processor was in when the resource
              access was made.
      addr -- The virtual address being accessed.  NOTE: This is an hword
              address, NOT a byte address!
      lanes -- A bitmap indicating which byte lanes are involved in the
              transfer.  Bit 0 corresponds to data bits 0-7, bit 1 to data
              bits 8-15.
      result -- Pointer to a variable that will receive any read values.
              Depending upon the lanes parameter, the upper byte, the lower
              byte, or both bytes of a 16-bit half-word will be affected.
      value -- The value to store into the resource.  Depending upon the
              lanes parameter, the data will be sourced either from bits
              8-15, 0-7, or both.
      error -- Pointer to a bool or gboolean variable indicating that
              an error has happened while processing the memory request.

 RESULT
      If everything was successful, *error is not modified.  Otherwise,
      the virtual resource is not affected in any way, and *error is set
      to true.

SEE ALSO

      cardslot_t, slots_t

cardslots/cardslot_s, cardslots/cardslot_t [ Structures ]

[ Top ] [ cardslots ] [ Structures ]

NAME

      struct cardslot_s
      cardslot_t

FUNCTION

Provide a single virtual to local memory mapping.

To resolve a virtual address (VA) to a local address, the first step is to apply an and-mask and a xor-mask like so:

              P = (VA & addr_and_mask) ^ xor_mask

If P evaluates to zero, we know we have a match; that is, this cardslot_t is responsible for handling the virtual address provided. If P evaluates to a non-zero value, this cardslot_t is not responsible, and you should look elsewhere.

Virtual addresses in the emulated environment are 32-bits wide, and MAY be between 24- and 32-bits in physical hardware. However, it is unlikely that any single card will provide gigabytes worth of storage on its own! Therefore, we need to constrain the address to just the significant bits that are considered "register selects". This will provide a byte offset into the card's resource space. In the electronics engineering field, this is called "partial address decoding."

For the purposes of emulation, once we have the byte offset in the card's resource space, we add the data pointer to acquire the actual local address.

              LA = (P & addr_sel_mask) + data

It is pretty rare to work directly with local addresses; usually you just want to do something with the virtual address you're given. For this reason, each cardslot_t provides three methods for fulfilling a processor request: you can read from the resource, write to the resource, or attempt to perform an instruction fetch from a resource.

MEMBERS

      addr_and_mask -- provides the AND mask, selecting which of the high
              bits of the virtual address to check for an address match.
      addr_xor_mask -- provides the XOR mask, selecting the precise value
              those high bits selected by the AND mask must equal in order
              to register a match.
      addr_sel_mask -- provides another AND mask, but these select the low-
              order memory address bits used to select a specific register
              or byte address in a memory resource.
      read, ifetch -- provides a callback which is invoked when something is
              trying to read (fetch an instruction from, resp.) from the
              card.  This gives the card's handler an opportunity to perform
              any desired side-effects as well (e.g., if writing to a color
              palette register, it can cause the display to change color).
      write -- provides a callback which is invoked when something is
              trying to write to the card.
      data -- For memory-type devices, this provides the local base address
              of the backing memory.

SEE ALSO

      slots_t, cardslot_rd_fn, cardslot_wr_fn

SOURCE

typedef struct cardslot_s {
        uint32_t        addr_and_mask;
        uint32_t        addr_xor_mask;
        uint32_t        addr_sel_mask;
        cardslot_rd_fn* read;
        cardslot_wr_fn* write;
        cardslot_rd_fn* ifetch;
        void*           data;
} cardslot_t;

cardslots/privilege_e, cardslots/privilege_t [ Types ]

[ Top ] [ cardslots ] [ Types ]

NAME

      enum privilege_e
      privilege_t

FUNCTION

Provides a way of symbolically expressing the desired RISC-V privilege mode with which to perform a memory access.

SOURCE

typedef enum privilege_e {
        PRIV_U = 0,
        PRIV_S = 1,
        PRIV_H = 2,
        PRIV_M = 3,
} privilege_t;

cardslots/slots_s, cardslots/slots_t [ Structures ]

[ Top ] [ cardslots ] [ Structures ]

NAME

      struct slots_s
      slots_t

FUNCTION

This structure provides a virtual to local memory mapping.

When performing an address translation or attempting to read/write from a card's address space, a search is performed from the start of the enclosed array of slots to the end. Therefore, it is wise to place the most frequently accessed resource into slot 0, the next most frequently accessed resource into slot 1, and so forth.

Up to CARDSLOTS_N_SLOTS slots are permitted.

MEMBERS

      slots_used -- the number of array elements in slots[] which hold valid
              mappings.

      slots -- an array of cardslot_t structures.

SEE ALSO

      cardslot_t

SOURCE

typedef struct slots_s {
        int        slots_used;
        cardslot_t slots[CARDSLOTS_N_SLOTS];
} slots_t;