From eb922f6ddce5d44d5aec2354a398f6b07bb76e74 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Mon, 25 May 2015 14:04:37 +0200 Subject: [PATCH] litesata: rework frontend doc and add striping, mirroring --- misoclib/mem/litesata/README | 4 +- .../doc/source/docs/frontend/index.rst | 198 +++++++++++++----- .../litesata/doc/source/docs/intro/about.rst | 4 +- .../doc/source/docs/simulation/index.rst | 18 +- 4 files changed, 164 insertions(+), 60 deletions(-) diff --git a/misoclib/mem/litesata/README b/misoclib/mem/litesata/README index db5aa9d5..a777a9da 100644 --- a/misoclib/mem/litesata/README +++ b/misoclib/mem/litesata/README @@ -59,9 +59,11 @@ Core: - Errors detection and reporting Frontend: - - Configurable crossbar (simply use core.crossbar.get_port() to add a new port!) + - Configurable crossbar (simply declare your crossbar and use crossbar.get_port() to add a new port!) - Ports arbitration transparent to the user - Synthetizable BIST + - Striping module to segment data on multiple HDDs and increase write/read speed and capacity. (RAID0 equivalent) + - Mirroring module for data redundancy and increase read speeds. (RAID1 equivalent) [> Possibles improvements ------------------------- diff --git a/misoclib/mem/litesata/doc/source/docs/frontend/index.rst b/misoclib/mem/litesata/doc/source/docs/frontend/index.rst index 51f0c6da..a7bf09e7 100644 --- a/misoclib/mem/litesata/doc/source/docs/frontend/index.rst +++ b/misoclib/mem/litesata/doc/source/docs/frontend/index.rst @@ -1,93 +1,191 @@ .. _frontend-index: ======================== -Frontend +Frontend interfaces ======================== -Crossbar and user ports -======================= - -LiteSATA provides a crossbar to let the user request the number of port he needs. -Ports are automatically arbitrated and dispatched to and from the core. In the -following example we create a core and get a port from the crossbar: - -.. code-block:: python - - self.submodules.sata_phy = LiteSATAPHY(platform.device, - platform.request("sata"), - "sata_gen2", - clk_freq) - self.submodules.sata = LiteSATA(self.sata_phy) - user_port = self.sata.crossbar.get_port() - -Our user_port has 2 endpoints: +All frontend modules of LiteSATA share the same user interface based on packets. +An interface has 2 endpoints: - A Sink used to send commands and write data. - - A Source used to receive commands acknowledges and receive read data. + - A Source used to receive commands acknowledges and read data. + +Packets and user commands/responses are described in the next sections. Packets description =================== Sink and Source are packets with additional parameters. A packet has the following signals: - - stb: Strobe signal indicates that command or data is valid. - - sop: Start Of Packet signal indicates that current command or data is the first of the packet. - - eop: End Of Packet signal indicates that current command or data is the last of the packet. - - ack: Response from the endpoint indicates that core is able to accept our command or data. - - data: Current data of the packet. + - :code:`stb`: Strobe signal indicates that command or data is valid. + - :code:`sop`: Start Of Packet signal indicates that current command or data is the first of the packet. + - :code:`eop`: End Of Packet signal indicates that current command or data is the last of the packet. + - :code:`ack`: Response from the endpoint indicates that core is able to accept our command or data. + - :code:`data`: Current data of the packet. .. figure:: packets.png - :scale: 30 % + :width: 50% :align: center An example of packet transaction between endpoints. .. tip:: - - When a packet only has a command or data, sop and eop must be set to 1 on the same clock cycle. - - A data is accepted when stb=1 and ack=1. + - When a packet only has a command or :code:`data`, :code:`sop` and :code:`eop` must be set to 1 on the same clock cycle. + - A :code:`data` is accepted when :code:`stb` =1 and :code:`ack` =1. User Commands ============= -All HDD transfers are initiated using the Sink endpoint which has the following signals: +All transfers are initiated using the Sink endpoint which has the following signals: - - write: 1 bit signal indicates if we want to write data to the HDD. - - read: 1 bit signal indicaties if we want to read data from the HDD. - - identify: 1 bit signal indicates if command is an identify device command (use to get HDD informations). - - sector: 48 bits signal, the sector number we are going to write or read. - - count: 16 bits signal, the number of sectors we are going to write or read. - - data: 32 bits signal, the write data. + - :code:`write`: 1 bit signal indicates if we want to write data to the HDD. + - :code:`read`: 1 bit signal indicaties if we want to read data from the HDD. + - :code:`identify`: 1 bit signal indicates if command is an identify device command (use to get HDD informations). + - :code:`sector`: 48 bits signal, the sector number we are going to write or read. + - :code:`count`: 16 bits signal, the number of sectors we are going to write or read. + - :code:`data`: n x 32 bits signal, the write data. (n depends of the frontend module) .. tip:: - - write, read, identify, sector, count are parameters so remain constant for a packet duration. - - sector, count are ignored during an identify command. - - data is ignored during a read or identify command. + - :code:`write`, :code:`read`, :code:`identify`, :code:`sector`, :code:`count` are parameters so remain constant for a packet duration. + - :code:`sector`, :code:`count` are ignored during an :code:`identify` command. + - :code:`data` is ignored during a :code:`read` or :code:`identify` command. User Responses ============== -HDD responses are obtained from the Source endpoint which has the following signals: +Responses are obtained from the Source endpoint which has the following signals: - - write: 1 bit signal indicates if command was a write. - - read: 1 bit signal indicaties if command was a read. - - identify: 1 bit signal indicates if command was an identify device command. - - last: 1 bit signal indicates if this is the last packet of the response. (A Response can be return in several packets) - - failed: 1 bit signal identicates if an error was detected in the response (CRC, FIS...) - - data: 32 bits signal, the read data + - :code:`write`: 1 bit signal indicates if command was a write. + - :code:`read`: 1 bit signal indicaties if command was a read. + - :code:`identify`: 1 bit signal indicates if command was an identify device command. + - :code:`last`: 1 bit signal indicates if this is the last packet of the response. (A response can be return in several packets) + - :code:`failed`: 1 bit signal identicates if an error was detected in the response (CRC, FIS...) + - :code:`data`: n x 32 bits signal, the read data. (n depends of the frontend module) .. tip:: - - write, read, identify, last are parameters so remain constant for a packet duration. - - data can be ignored in the case of a write or identify command. - - in case of a read command, read data packets are presented followed by an empty packet indicating the end of the transaction (last=1). + - :code:`write`, :code:`read`, :code:`identify`, :code:`last` are parameters so remain constant for a packet duration. + - :code:`data` can be ignored in the case of a :code:`write` or :code:`identify` command. + - in case of a :code:`read` command, read data packets are presented followed by an empty packet indicating the end of the transaction (last=1). + +======================== +Frontend modules +======================== + +LiteSATA provides a configurable and flexible frontend that can be used to: + +- Provides any number of user ports. +- Generate any RAID configuration when used with multiple HDDs. + +Crossbar +======== + +The crossbar let the user request any number of ports. It automatically arbitrate requests and dispatch responses to the corresponding ports. + +The following example creates a crossbar and 2 user ports: + +.. code-block:: python + + self.submodules.sata_crossbar = LiteSATACrossbar(self.sata_core) + user_port0 = self.sata_crossbar.get_port() + user_port1 = self.sata_crossbar.get_port() + +Striping +======== + +The striping module segment data so that data is stored on N different controllers. (RAID0 equivalent) + +.. code-block:: python + + +----> controller0 (dw) + port (N*dw) <----+----> controllerX (dw) + +----> controllerN (dw) + +Characteristics: + - :code:`port`'s visible capacity = N x :code:`controller`'s visible capacity + - :code:`port`'s throughput = N x (slowest) :code:`controller`'s throughput + +It can be used to increase capacity and writes/reads speed. + +The following example creates a striping with 2 HDDs: + +.. code-block:: python + + self.submodules.sata_striping = LiteSATAStriping([self.sata_core0, self.sata_core1]) + +:code:`sata_striping`'s sink and source are the user interface. + +Mirroring +========= + +The mirroring module handles N controllers and provides N ports. (RAID1 equivalent) + +Each port has its dedicated controller for reads: + +.. code-block:: python + + port0 <----> controller0 + portX <----> controllerX + portN <----> controllerN + +Writes are mirrored on each controller: + +.. code-block:: python + + (port0 write) | (portN write) + port0 ----------+----> controller0 | port0 (stalled) +-----> controller0 + portX (stalled) +----> controllerX | portX (stalled) +-----> controllerX + portN (stalled) +----> controllerN | portN ----------+-----> controllerN + +Writes have priority on reads. When a write is presented on one of the port, the module waits for all ongoing reads to finish and commute to write mode. Once all writes are serviced it returns to read mode. + +Characteristics: + - :code:`port`'s visible capacity = :code:`controller`'s visible capacity + - total writes throughput = (slowest) :code:`controller`'s throughput + - total reads throughput = N x :code:`controller`'s throughput + +It can be used for data redundancy and/or to increase total reads speed. + +.. code-block:: python + + self.submodules.sata_mirroring = LiteSATAMirroring([self.sata_core0, self.sata_core1]) + +:code:`sata_striping`'s ports[0] and ports[1] are the user interfaces. + +Modules combinations +==================== + +Since all frontend modules share the same interface, it's easy to combine them together. + +In the following code, we have 4 HDDs, do a striping with (0,1) and (2,3), a mirroring on top of that and then create a crossbar on the first port of our mirroring module: + +.. code-block:: python + + self.submodules.sata_striping0 = LiteSATAStriping([self.sata_core0, self.sata_core1]) + self.submodules.sata_striping1 = LiteSATAStriping([self.sata_core2, self.sata_core3]) + self.submodules.sata_mirroring = LiteSATAMirroring([self.sata_striping0, self.sata_striping1]) + self.submodules.sata_crossbar = LiteSATACrossbar(self.sata_mirroring.ports[0]) + self.user_port0 = self.sata_crossbar.get_port() + self.user_port1 = self.sata_crossbar.get_port() + +This code provides the following user interfaces: :code:`self.user_port0`, :code:`self.user_port1` and :code:`self.sata_mirroring.ports[1]`. + Examples ======== -A BIST_ (Data generator and checker) design is provided. It can be used to understand how to connect -your logic to the user_port provided by the crossbar. (See LiteSATABISTGenerator, LiteSATABISTChecker and LiteSATABISTIdentify) +Since it's probably easier to figure out how to use the frontend modules with real use cases, we provides example designs: + +- A BIST_ (Data generator and checker) design that can be used to understand how to connect your logic to the user_port provided by the crossbar. + +- A Striping_ design that can be used to understand how to connect couple 4 HDDs together in striping mode and do a BIST it. + +- A Mirroring_ design that can be used to understand how to connect couple 4 HDDs together in Mirroring mode and do a BIST it. + +.. _BIST: https://github.com/m-labs/misoc/blob/master/misoclib/mem/litesata/example_designs/targets/bist.py -.. _BIST: https://github.com/m-labs/misoc/blob/master/misoclib/mem/litesata/frontend/bist.py +.. _Striping: https://github.com/m-labs/misoc/blob/master/misoclib/mem/litesata/example_designs/targets/striping.py +.. _Mirroring: https://github.com/m-labs/misoc/blob/master/misoclib/mem/litesata/example_designs/targets/mirroring.py diff --git a/misoclib/mem/litesata/doc/source/docs/intro/about.rst b/misoclib/mem/litesata/doc/source/docs/intro/about.rst index e39a8ddb..207d9acb 100644 --- a/misoclib/mem/litesata/doc/source/docs/intro/about.rst +++ b/misoclib/mem/litesata/doc/source/docs/intro/about.rst @@ -50,9 +50,11 @@ Core: - Errors detection and reporting Frontend: - - Configurable crossbar (simply use core.crossbar.get_port() to add a new port!) + - Configurable crossbar (simply declare your crossbar and use core.crossbar.get_port() to add a new port!) - Ports arbitration transparent to the user - Synthetizable BIST + - Striping module to segment data on multiple HDDs and increase write/read speed and capacity. (RAID0 equivalent) + - Mirroring module for data redundancy and increase read speeds. (RAID1 equivalent) Possibles improvements diff --git a/misoclib/mem/litesata/doc/source/docs/simulation/index.rst b/misoclib/mem/litesata/doc/source/docs/simulation/index.rst index 22bedbd5..e75d259d 100644 --- a/misoclib/mem/litesata/doc/source/docs/simulation/index.rst +++ b/misoclib/mem/litesata/doc/source/docs/simulation/index.rst @@ -7,14 +7,16 @@ Simulation .. note:: Please contribute to this document, or support us financially to write it. -Simulations are available in ./lib/sata/test: - - crc_tb - - scrambler_tb - - phy_datapath_tb - - link_tb - - command_tb - - bist_tb +Simulations are available in ./test: + - :code:`crc_tb` + - :code:`scrambler_tb` + - :code:`phy_datapath_tb` + - :code:`link_tb` + - :code:`command_tb` + - :code:`bist_tb` + - :code:`striping_tb` + - :code:`mirroring_tb` Models for all the layers of SATA and a simplified HDD model are provided. To run a simulation, go to ./test and run: - - make \ No newline at end of file + - :code:`make ` \ No newline at end of file -- 2.30.2