source: trunk/modules/vci_spi/caba/source/src/vci_spi.cpp @ 579

Last change on this file since 579 was 579, checked in by bouyer, 10 years ago

Add some basic DMA capabilities. Passes basic read/write tests.
Can only do line-aligned transfers which are multiple of a cache line in size,
but shouldn't be a strong limitation for real use.

File size: 22.2 KB
Line 
1/* -*- c++ -*-
2 *
3 * SOCLIB_LGPL_HEADER_BEGIN
4 *
5 * This file is part of SoCLib, GNU LGPLv2.1.
6 *
7 * SoCLib is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation; version 2.1 of the License.
10 *
11 * SoCLib is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with SoCLib; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 * 02110-1301 USA
20 *
21 * SOCLIB_LGPL_HEADER_END
22 *
23 * Copyright (c) UPMC, Lip6, SoC
24 *       manuel.bouyer@lip6.fr october 2013
25 *
26 * Maintainers: bouyer
27 */
28
29#include <stdint.h>
30#include <iostream>
31#include <arithmetics.h>
32#include <fcntl.h>
33#include "vci_spi.h"
34#include "vcispi.h"
35
36namespace soclib { namespace caba {
37
38#define tmpl(t) template<typename vci_param> t VciSpi<vci_param>
39
40using namespace soclib::caba;
41using namespace soclib::common;
42
43////////////////////////
44tmpl(void)::transition()
45{
46
47    bool s_dma_bsy = (r_initiator_fsm != M_IDLE);
48    if(p_resetn.read() == false) 
49    {
50        r_initiator_fsm   = M_IDLE;
51        r_target_fsm      = T_IDLE;
52        r_spi_fsm         = S_IDLE;
53        r_ss              = 0;
54        r_divider         = 0xffff;
55        r_ctrl_char_len   = 0;
56        r_ctrl_ie         = false;
57        r_ctrl_cpol       = false;
58        r_ctrl_cpha       = false;
59        r_spi_bsy         = false;
60        r_dma_count       = 0;
61        r_spi_clk_counter = 0xffff;
62        r_spi_clk         = 0;
63        r_spi_done        = false;
64
65        r_irq             = false;
66        r_read            = false;
67
68        r_dma_fifo_read.init();
69        r_dma_fifo_write.init();
70
71        return;
72    } 
73
74    //////////////////////////////////////////////////////////////////////////////
75    // The Target FSM controls the following registers:
76    // r_target_fsm, r_irq_enable, r_nblocks, r_buf adress, r_lba, r_go, r_read
77    //////////////////////////////////////////////////////////////////////////////
78
79    if (r_spi_done)
80        r_spi_bsy = false;
81
82    switch(r_target_fsm) {
83    ////////////
84    case T_IDLE:
85    {
86        if ( p_vci_target.cmdval.read() ) 
87        { 
88            r_srcid = p_vci_target.srcid.read();
89            r_trdid = p_vci_target.trdid.read();
90            r_pktid = p_vci_target.pktid.read();
91            uint32_t wdata = p_vci_target.wdata.read();
92            sc_dt::sc_uint<vci_param::N> address = p_vci_target.address.read();
93
94            bool found = false;
95            std::list<soclib::common::Segment>::iterator seg;
96            for ( seg = m_seglist.begin() ; seg != m_seglist.end() ; seg++ ) 
97            {
98                if ( seg->contains(address) ) found = true;
99            }
100 
101
102            if (not found) {
103                if (p_vci_target.cmd.read() == vci_param::CMD_WRITE)
104                    r_target_fsm = T_ERROR_WRITE;
105                else
106                    r_target_fsm = T_ERROR_READ;
107            } else if (p_vci_target.cmd.read() != vci_param::CMD_READ &&
108                       p_vci_target.cmd.read() != vci_param::CMD_WRITE) {
109                r_target_fsm = T_ERROR_READ;
110            } else {
111                bool     write  = (p_vci_target.cmd.read() == vci_param::CMD_WRITE) & !r_spi_bsy &!s_dma_bsy;
112                uint32_t cell   = (uint32_t)((address & 0x3F)>>2);
113                switch(cell) {
114                case SPI_DATA_TXRX0:
115                    r_rdata = r_txrx[0] & (uint64_t)0x00000000ffffffffULL;
116                    if (write) {
117                        r_txrx[0] =
118                           (r_txrx[0] & (uint64_t)0xffffffff00000000ULL) |
119                           ((uint64_t)wdata);
120                    }
121                    r_target_fsm = (p_vci_target.cmd.read() == vci_param::CMD_WRITE) ? T_RSP_WRITE : T_RSP_READ;
122                    break;
123                case SPI_DATA_TXRX1:
124                    r_rdata = r_txrx[0] >> 32;
125                    if (write) {
126                        r_txrx[0] =
127                            (r_txrx[0] & (uint64_t)0x00000000ffffffffULL) |
128                            ((uint64_t)wdata << 32);
129                    }
130                    r_target_fsm = (p_vci_target.cmd.read() == vci_param::CMD_WRITE) ? T_RSP_WRITE : T_RSP_READ;
131                    break;
132                case SPI_DATA_TXRX2:
133                    r_rdata = r_txrx[1] & (uint64_t)0x00000000ffffffffULL;
134                    if (write) {
135                        r_txrx[1] =
136                           (r_txrx[1] & (uint64_t)0xffffffff00000000ULL) |
137                           ((uint64_t)wdata);
138                    }
139                    r_target_fsm = (p_vci_target.cmd.read() == vci_param::CMD_WRITE) ? T_RSP_WRITE : T_RSP_READ;
140                    break;
141                case SPI_DATA_TXRX3:
142                    r_rdata = r_txrx[1] >> 32;
143                    if (write) {
144                        r_txrx[1] =
145                            (r_txrx[1] & (uint64_t)0x00000000ffffffffULL) |
146                            ((uint64_t)wdata << 32);
147                    }
148                    r_target_fsm = (p_vci_target.cmd.read() == vci_param::CMD_WRITE) ? T_RSP_WRITE : T_RSP_READ;
149                    break;
150                case SPI_CTRL:
151                {
152                    uint32_t data = 0;
153                    if (r_ctrl_cpol.read()) 
154                        data |= SPI_CTRL_CPOL;
155                    if (r_ctrl_cpha.read()) 
156                        data |= SPI_CTRL_CPHA;
157                    if (r_ctrl_ie.read()) 
158                        data |= SPI_CTRL_IE_EN;
159                    if (r_spi_bsy.read()) 
160                        data |= SPI_CTRL_GO_BSY;
161                    if (s_dma_bsy) 
162                        data |= SPI_CTRL_DMA_BSY;
163                    data |= (uint32_t)r_ctrl_char_len.read();
164                    r_rdata = data;
165                    if (write) {
166                        r_ctrl_cpol = ((wdata & SPI_CTRL_CPOL) != 0);
167                        r_ctrl_cpha = ((wdata & SPI_CTRL_CPHA) != 0);
168                        r_ctrl_ie  = ((wdata & SPI_CTRL_IE_EN) != 0);
169                        if (wdata & SPI_CTRL_GO_BSY) 
170                                r_spi_bsy = true;
171                        r_ctrl_char_len = (wdata & SPI_CTRL_CHAR_LEN_MASK);
172#ifdef SOCLIB_MODULE_DEBUG
173                        if ((wdata & SPI_CTRL_GO_BSY) != 0) {
174                            std::cout << name() << " start xfer " << std::dec << (int)r_ctrl_char_len.read() << " data " << std::hex << r_txrx[1] << " " << r_txrx[0] << std::endl;
175                        }
176#endif
177                    } else {
178                        r_irq = r_irq & r_spi_bsy;
179                    }
180                    r_target_fsm = (p_vci_target.cmd.read() == vci_param::CMD_WRITE) ? T_RSP_WRITE : T_RSP_READ;
181                    break;
182                }
183                case SPI_DIVIDER:
184                    r_rdata = r_divider.read();
185                    if (write) {
186#ifdef SOCLIB_MODULE_DEBUG
187                        std::cout << name() << " divider set to " << std::dec << wdata << std::endl;
188#endif
189                        r_divider = wdata;
190                    }
191                    r_target_fsm = (p_vci_target.cmd.read() == vci_param::CMD_WRITE) ? T_RSP_WRITE : T_RSP_READ;
192                    break;
193                case SPI_SS:
194                    r_rdata = r_ss.read();
195                    if (write) {
196                        r_ss = wdata;
197                    }
198                    r_target_fsm = (p_vci_target.cmd.read() == vci_param::CMD_WRITE) ? T_RSP_WRITE : T_RSP_READ;
199                    break;
200                case SPI_DMA_BASE:
201                    r_rdata = r_buf_address.read();
202                    if (write) {
203                        r_buf_address = (r_buf_address & (uint64_t)0xffffffff00000000) | wdata;
204                    }
205                    r_target_fsm = (p_vci_target.cmd.read() == vci_param::CMD_WRITE) ? T_RSP_WRITE : T_RSP_READ;
206                    break;
207                case SPI_DMA_BASEH:
208                    r_rdata = r_buf_address >> 32;
209                    if (write) {
210                        r_buf_address = (r_buf_address & (uint64_t)0x00000000ffffffff) | ((uint64_t)wdata << 32);
211                    }
212                    r_target_fsm = (p_vci_target.cmd.read() == vci_param::CMD_WRITE) ? T_RSP_WRITE : T_RSP_READ;
213                    break;
214                case SPI_DMA_COUNT:
215                    r_rdata = (r_dma_count.read() << m_byte2burst_shift) |
216                        r_read;
217                    if (write) {
218                        r_read = (wdata & 0x1);
219                        r_dma_count = wdata >> m_byte2burst_shift;
220                        r_ctrl_char_len = vci_param::B * 8;
221                    }
222                    r_target_fsm = (p_vci_target.cmd.read() == vci_param::CMD_WRITE) ? T_RSP_WRITE : T_RSP_READ;
223                    break;
224                default:
225                    r_target_fsm = (p_vci_target.cmd.read() == vci_param::CMD_WRITE) ? T_ERROR_WRITE : T_ERROR_READ;
226                    break;
227                }
228            }
229        }
230        break;
231    }
232    ////////////////////
233    case T_RSP_READ:
234    case T_RSP_WRITE:
235    case T_ERROR_READ:
236    case T_ERROR_WRITE:
237        if (p_vci_target.rspack.read() ) {
238            r_target_fsm  = T_IDLE;
239        }
240        break;
241    } // end switch target fsm
242
243
244       
245
246    //////////////////////////////////////////////////////////////////////////////
247    // the SPI FSM controls SPI signals
248    //////////////////////////////////////////////////////////////////////////////
249    if (r_spi_bsy == false)
250        r_spi_done = false;
251    switch (r_spi_fsm) {
252    case S_IDLE:
253        r_spi_clk_counter = r_divider.read();
254        r_spi_clk = 0;
255        r_spi_clk_previous = r_ctrl_cpha;
256        r_spi_clk_ignore = r_ctrl_cpha;
257        r_spi_bit_count = r_ctrl_char_len;
258        r_spi_out = (r_txrx[(r_ctrl_char_len -1)/ 64] >> ((r_ctrl_char_len - 1) % 64)) & (uint64_t)0x0000000000000001ULL;
259        if (r_dma_count != 0) {
260                if (r_read.read())
261                        r_spi_fsm = S_DMA_SEND_START;
262                else
263                        r_spi_fsm = S_DMA_RECEIVE;
264        } else if (r_spi_bsy.read() && !r_spi_done.read()) {
265            r_spi_fsm = S_XMIT;
266        }
267        break;
268    case S_DMA_RECEIVE:
269    {
270        r_spi_clk_counter = r_divider.read();
271        r_spi_clk = 0;
272        r_spi_clk_previous = r_ctrl_cpha;
273        r_spi_clk_ignore = r_ctrl_cpha;
274        r_spi_bit_count = r_ctrl_char_len;
275        if (r_initiator_fsm != M_WRITE_RSP || !p_vci_initiator.rspval.read()) {
276            if (r_dma_fifo_write.rok()) {
277                typename vci_param::data_t v = r_dma_fifo_write.read();
278                r_dma_fifo_write.simple_get();
279                r_txrx[0] = v;
280                r_spi_out = (v >> ((vci_param::B * 8) - 1)) & 0x1;
281                r_spi_fsm = S_XMIT;
282            } else if (r_initiator_fsm == M_WRITE_END) {
283                r_spi_fsm = S_IDLE;
284            }
285        }
286        break;
287    }
288    case S_DMA_SEND_START:
289        r_spi_word_count = (r_dma_count << (m_byte2burst_shift - 2)) - 1;
290        r_spi_out = 1;
291        r_txrx[0] = 0xffffffff;
292        r_spi_fsm = S_XMIT;
293        break;
294    case S_DMA_SEND:
295        r_spi_out = 1;
296        r_txrx[0] = 0xffffffff;
297        r_spi_clk_counter = r_divider.read();
298        r_spi_clk = 0;
299        r_spi_clk_previous = r_ctrl_cpha;
300        r_spi_clk_ignore = r_ctrl_cpha;
301        r_spi_bit_count = r_ctrl_char_len;
302        if (r_initiator_fsm != M_READ_CMD) {
303            if (r_dma_fifo_read.wok()) {
304                r_dma_fifo_read.simple_put(
305                    (typename vci_param::data_t)r_txrx[0]);
306                r_spi_word_count = r_spi_word_count - 1;
307                if ( r_spi_word_count == 0 ) {
308                    r_spi_fsm = S_DMA_SEND_END;
309                } else {
310                    r_spi_fsm = S_XMIT;
311                }
312            }
313        }
314        break;
315    case S_DMA_SEND_END:
316        if (r_initiator_fsm == M_IDLE)
317                r_spi_fsm = S_IDLE;
318        break;
319    case S_XMIT:
320      {
321        bool s_clk_sample;
322        // on clock transition, sample input line, and shift data
323        s_clk_sample = r_spi_clk ^ r_ctrl_cpha;
324        if (!r_spi_clk_ignore) {
325            if (r_spi_clk_previous == 0 && s_clk_sample == 1) {
326                // low to high transition: shift and sample
327                r_txrx[1] = (r_txrx[1] << 1) | (r_txrx[0] >> 63);
328                r_txrx[0] = (r_txrx[0] << 1) | p_spi_miso;
329                r_spi_bit_count = r_spi_bit_count - 1;
330            } else if (r_spi_clk_previous == 1 && s_clk_sample == 0) {
331                // high to low transition: change output, or stop
332                if (r_spi_bit_count == 0) {
333                    if (r_initiator_fsm != M_IDLE) {
334                        if (r_read)
335                            r_spi_fsm = S_DMA_SEND;
336                        else
337                            r_spi_fsm = S_DMA_RECEIVE;
338                    } else {
339                        r_spi_fsm = S_IDLE;
340                        r_irq = r_ctrl_ie;
341                        r_spi_done = true;
342                    }
343#ifdef SOCLIB_MODULE_DEBUG0
344                    std::cout << name() << " end xfer " << std::dec << (int)r_ctrl_char_len.read() << " data " << std::hex << r_txrx[1] << " " << r_txrx[0] << std::endl;
345#endif
346                } else {
347                    r_spi_out = (r_txrx[(r_ctrl_char_len -1)/ 64] >> ((r_ctrl_char_len - 1) % 64)) & (uint64_t)0x0000000000000001ULL;
348                }
349            }
350        }
351        r_spi_clk_previous = s_clk_sample;
352        // generate the SPI clock
353        if (r_spi_clk_counter.read() == 0) {
354            r_spi_clk_counter = r_divider.read();
355            r_spi_clk = !r_spi_clk.read();
356            r_spi_clk_ignore = false;
357        } else {
358            r_spi_clk_counter = r_spi_clk_counter.read() - 1;
359        }
360        break;
361      }
362    }
363    //////////////////////////////////////////////////////////////////////////////
364    // The initiator FSM executes a loop, transfering one burst per iteration.
365    // data comes from or goes to fifos, the other end of the fifos is
366    // feed by or eaten by the SPI fsm.
367    //////////////////////////////////////////////////////////////////////////////
368
369    switch( r_initiator_fsm.read() ) {
370    ////////////
371    case M_IDLE:        // check buffer alignment to compute the number of bursts
372    {
373        if ( r_dma_count != 0 )
374        {
375            // start transfer
376            if ( r_read.read() )    r_initiator_fsm = M_READ_WAIT;
377            else                    r_initiator_fsm = M_WRITE_WAIT;
378        }
379        break;
380    }
381    case M_READ_WAIT:  // wait for the FIFO to be full
382        if (!r_dma_fifo_read.wok()) {
383                r_burst_word = m_words_per_burst - 1;
384                r_initiator_fsm = M_READ_CMD;
385        }
386        break;
387    ////////////////
388    case M_READ_CMD:    // Send a multi-flits VCI WRITE command
389    {
390        if ( p_vci_initiator.cmdack.read() )
391        {
392            if ( r_burst_word == 0 )      // last flit
393            {
394                r_initiator_fsm = M_READ_RSP;
395            }
396            else                    // not the last flit
397            {
398                r_burst_word = r_burst_word.read() - 1;
399            }
400
401            r_dma_fifo_read.simple_get(); // consume one fifo word
402            // compute next word address
403            r_buf_address = r_buf_address.read() + vci_param::B;
404        }
405        break;
406    }
407    ////////////////
408    case M_READ_RSP:    // Wait a single flit VCI WRITE response
409    {
410        if ( p_vci_initiator.rspval.read() )
411        {
412            if ( (p_vci_initiator.rerror.read()&0x1) != 0 ) 
413            {
414                r_burst_word = 0;
415                r_dma_count = 0;
416                r_dma_error = true;
417                r_initiator_fsm = M_IDLE;
418#ifdef SOCLIB_MODULE_DEBUG
419                std::cout << "vci_bd M_READ_ERROR" << std::endl;
420#endif
421            }
422            else if ( r_spi_fsm == S_DMA_SEND_END ) // last burst
423            {
424                r_dma_count = 0;
425                r_initiator_fsm = M_IDLE;
426                r_dma_error = false;
427#ifdef SOCLIB_MODULE_DEBUG
428                std::cout << "vci_bd M_READ_SUCCESS" << std::endl;
429#endif
430            }
431            else // keep on reading
432            {
433                r_dma_count = r_dma_count - 1;
434                r_initiator_fsm  = M_READ_WAIT;
435            }
436        }
437        break;
438    }
439    ///////////////////
440    case M_WRITE_WAIT:  // wait for the FIFO to be empty
441        if (!r_dma_fifo_write.rok()) {
442            r_burst_word = m_words_per_burst - 1;
443            r_dma_count = r_dma_count - 1;
444            r_initiator_fsm = M_WRITE_CMD;
445        }
446        break;
447    /////////////////
448    case M_WRITE_CMD:   // This is actually a single flit VCI READ command
449    {
450        if ( p_vci_initiator.cmdack.read() ) r_initiator_fsm = M_WRITE_RSP;
451        break;
452    }
453    /////////////////
454    case M_WRITE_RSP:   // This is actually a multi-words VCI READ response
455    {
456        if ( p_vci_initiator.rspval.read() )
457        {
458            typename vci_param::data_t v = p_vci_initiator.rdata.read();
459            typename vci_param::data_t f = 0;
460            // byte-swap
461            for (int i = 0; i < (vci_param::B * 8); i += 8) {
462                f |= ((v >> i) & 0xff) << ((vci_param::B * 8) - 8 - i);
463            }
464            r_dma_fifo_write.simple_put(f);
465            r_burst_word = r_burst_word.read() - 1;
466            if ( p_vci_initiator.reop.read() )  // last flit of the burst
467            {
468                r_buf_address = r_buf_address.read() + m_burst_size;
469
470                if( (p_vci_initiator.rerror.read()&0x1) != 0 ) 
471                {
472                    r_dma_count = 0;
473                    r_dma_error = 1;
474                    r_initiator_fsm = M_WRITE_END;
475#ifdef SOCLIB_MODULE_DEBUG
476                    std::cout << "vci_bd M_WRITE_ERROR" << std::endl;
477#endif
478                }
479                else if ( r_dma_count.read() == 0) // last burst
480                {
481                    r_dma_error = 0;
482                    r_initiator_fsm  = M_WRITE_END;
483                }
484                else                                      // not the last burst
485                {
486                    r_initiator_fsm = M_WRITE_WAIT;
487                }
488            }
489        }
490        break;
491    }
492    /////////////////
493    case M_WRITE_END:   // wait for the write to be complete
494    {
495        if (r_spi_fsm == S_IDLE) { // write complete
496            r_initiator_fsm  = M_IDLE;
497        }
498        break;
499    }
500  } // end switch r_initiator_fsm
501}  // end transition
502
503//////////////////////
504tmpl(void)::genMoore()
505{
506    // p_vci_target port   
507    p_vci_target.rsrcid = (sc_dt::sc_uint<vci_param::S>)r_srcid.read();
508    p_vci_target.rtrdid = (sc_dt::sc_uint<vci_param::T>)r_trdid.read();
509    p_vci_target.rpktid = (sc_dt::sc_uint<vci_param::P>)r_pktid.read();
510    p_vci_target.reop   = true;
511
512    switch(r_target_fsm) {
513    case T_IDLE:
514        p_vci_target.cmdack = true;
515        p_vci_target.rspval = false;
516        p_vci_target.rdata  = 0;
517        break;
518    case T_RSP_READ:
519        p_vci_target.cmdack = false;
520        p_vci_target.rspval = true;
521        p_vci_target.rdata = r_rdata;
522        p_vci_target.rerror = VCI_READ_OK;
523        break;
524    case T_RSP_WRITE:
525        p_vci_target.cmdack = false;
526        p_vci_target.rspval = true;
527        p_vci_target.rdata  = 0;
528        p_vci_target.rerror = VCI_WRITE_OK;
529        break;
530    case T_ERROR_READ:
531        p_vci_target.cmdack = false;
532        p_vci_target.rspval = true;
533        p_vci_target.rdata  = 0;
534        p_vci_target.rerror = VCI_READ_ERROR;
535        break;
536    case T_ERROR_WRITE:
537        p_vci_target.cmdack = false;
538        p_vci_target.rspval = true;
539        p_vci_target.rdata  = 0;
540        p_vci_target.rerror = VCI_WRITE_ERROR;
541        break;
542    } // end switch target fsm
543
544    // p_vci_initiator port
545    p_vci_initiator.srcid  = (sc_dt::sc_uint<vci_param::S>)m_srcid;
546    p_vci_initiator.trdid  = 0;
547    p_vci_initiator.contig = true;
548    p_vci_initiator.cons   = false;
549    p_vci_initiator.wrap   = false;
550    p_vci_initiator.cfixed = false;
551    p_vci_initiator.clen   = 0;
552
553    switch (r_initiator_fsm) {
554    case M_WRITE_CMD:           // It is actually a single flit VCI read command
555        p_vci_initiator.rspack  = false;
556        p_vci_initiator.cmdval  = true;
557        p_vci_initiator.address = (sc_dt::sc_uint<vci_param::N>)r_buf_address.read();
558        p_vci_initiator.cmd     = vci_param::CMD_READ;
559        p_vci_initiator.pktid   = TYPE_READ_DATA_UNC; 
560        p_vci_initiator.wdata   = 0;
561        p_vci_initiator.be      = 0;
562        p_vci_initiator.plen    = (sc_dt::sc_uint<vci_param::K>)(m_burst_size);
563        p_vci_initiator.eop     = true;
564        break;
565    case M_READ_CMD:            // It is actually a multi-words VCI WRITE command
566    {
567        typename vci_param::data_t v = 0;
568        typename vci_param::data_t f;
569        p_vci_initiator.rspack  = false;
570        p_vci_initiator.cmdval  = true;
571        p_vci_initiator.address = (sc_dt::sc_uint<vci_param::N>)r_buf_address.read();
572        p_vci_initiator.cmd     = vci_param::CMD_WRITE;
573        p_vci_initiator.pktid   = TYPE_WRITE;
574        p_vci_initiator.plen    = (sc_dt::sc_uint<vci_param::K>)(m_burst_size);
575        f = r_dma_fifo_read.read();
576        // byte-swap
577        for (int i = 0; i < (vci_param::B * 8); i += 8) {
578                v |= ((f >> i) & 0xff) << ((vci_param::B * 8) - 8 - i);
579        }
580        p_vci_initiator.wdata = v;
581        p_vci_initiator.eop   = ( r_burst_word.read() == 0);
582        if (vci_param::B == 8)
583        {
584            p_vci_initiator.be    = 0xFF;
585        }
586        else
587        {
588            p_vci_initiator.be    = 0xF;
589        }
590        break;
591    }
592    case M_READ_RSP:
593    case M_WRITE_RSP:
594        p_vci_initiator.rspack  = true;
595        p_vci_initiator.cmdval  = false;
596        break;
597    default:
598        p_vci_initiator.rspack  = false;
599        p_vci_initiator.cmdval  = false;
600        break;
601    }
602
603    // SPI signals
604    p_spi_ss = ((r_ss & 0x1) == 0);
605    switch(r_spi_fsm) {
606    default:
607        p_spi_mosi = r_spi_out;
608        p_spi_clk = 0;
609        break;
610    case S_XMIT:
611      {
612        bool s_clk_sample = r_spi_clk ^ r_ctrl_cpha;
613        p_spi_clk = r_spi_clk ^ r_ctrl_cpol;
614        if (s_clk_sample == 0) {
615            // clock low: get data directly from shift register
616            // as r_spi_out may be delayed by one clock cycle
617            p_spi_mosi = (r_txrx[(r_ctrl_char_len -1)/ 64] >> ((r_ctrl_char_len - 1) % 64)) & (uint64_t)0x0000000000000001ULL;
618        } else {
619            // clock high: get data from saved value, as the shift register
620            // may have changed
621            p_spi_mosi = r_spi_out;
622        }
623        break;
624      }
625    }
626
627    // IRQ signal
628    p_irq = r_irq;
629} // end GenMoore()
630
631//////////////////////////////////////////////////////////////////////////////
632tmpl(/**/)::VciSpi( sc_core::sc_module_name           name, 
633                                const soclib::common::MappingTable   &mt,
634                                const soclib::common::IntTab     &srcid,
635                                const soclib::common::IntTab     &tgtid,
636                                const uint32_t                 burst_size)
637
638: caba::BaseModule(name),
639        m_seglist(mt.getSegmentList(tgtid)),
640        m_srcid(mt.indexForId(srcid)),
641        m_burst_size(burst_size),
642        m_words_per_burst(burst_size / vci_param::B),
643        m_byte2burst_shift(soclib::common::uint32_log2(burst_size)),
644        p_clk("p_clk"),
645        p_resetn("p_resetn"),
646        p_vci_initiator("p_vci_initiator"),
647        p_vci_target("p_vci_target"),
648        p_irq("p_irq"),
649        p_spi_ss("p_spi_ss"),
650        p_spi_clk("p_spi_clk"),
651        p_spi_mosi("p_spi_mosi"),
652        p_spi_miso("p_spi_miso"),
653
654        r_dma_fifo_read("r_dma_fifo_read", burst_size / vci_param::B), // one cache line
655        r_dma_fifo_write("r_dma_fifo_read", burst_size / vci_param::B) // one cache line
656{
657    std::cout << "  - Building VciSpi " << name << std::endl;
658
659        SC_METHOD(transition);
660    dont_initialize();
661    sensitive << p_clk.pos();
662
663        SC_METHOD(genMoore);
664    dont_initialize();
665    sensitive << p_clk.neg();
666
667    size_t nbsegs = 0;
668    std::list<soclib::common::Segment>::iterator seg;
669    for ( seg = m_seglist.begin() ; seg != m_seglist.end() ; seg++ ) 
670    {
671        nbsegs++;
672       
673            if ( (seg->baseAddress() & 0x0000003F) != 0 ) 
674            {
675                    std::cout << "Error in component VciSpi : " << name
676                              << "The base address of segment " << seg->name()
677                      << " must be multiple of 64 bytes" << std::endl;
678                    exit(1);
679            }
680            if ( seg->size() < 64 ) 
681            {
682                    std::cout << "Error in component VciSpi : " << name
683                          << "The size of segment " << seg->name()
684                      << " cannot be smaller than 64 bytes" << std::endl;
685                    exit(1);
686            }
687        std::cout << "    => segment " << seg->name()
688                  << " / base = " << std::hex << seg->baseAddress()
689                  << " / size = " << seg->size() << std::endl; 
690    }
691
692    if( nbsegs == 0 )
693    {
694                std::cout << "Error in component VciSpi : " << name
695                          << " No segment allocated" << std::endl;
696                exit(1);
697    }
698
699    if( (burst_size != 8 ) && 
700                (burst_size != 16) && 
701                (burst_size != 32) && 
702                (burst_size != 64) )
703        {
704                std::cout << "Error in component VciSpi : " << name
705                          << " The burst size must be 8, 16, 32 or 64 bytes" << std::endl;
706                exit(1);
707        }
708
709        if ( (vci_param::B != 4) and (vci_param::B != 8) )
710        {
711                std::cout << "Error in component VciSpi : " << name           
712                          << " The VCI data fields must have 32 bits or 64 bits" << std::endl;
713                exit(1);
714        }
715
716} // end constructor
717
718tmpl(/**/)::~VciSpi()
719{
720}
721
722
723//////////////////////////
724tmpl(void)::print_trace()
725{
726        const char* initiator_str[] = 
727    {
728                "M_IDLE",
729
730                "M_READ_WAIT",
731                "M_READ_CMD",
732                "M_READ_RSP",
733
734                "M_WRITE_WAIT",
735                "M_WRITE_CMD",
736                "M_WRITE_RSP",
737                "M_WRITE_END",
738        };
739        const char* target_str[] = 
740        {
741                "T_IDLE",
742                "T_RSP_READ",
743                "T_RSP_WRITE",
744                "T_ERROR_READ",
745                "T_ERROR_WRITE",
746        };
747        const char* spi_str[] = 
748        {
749                "S_IDLE",
750                "S_DMA_RECEIVE",
751                "S_DMA_SEND_START",
752                "S_DMA_SEND",
753                "S_DMA_SEND_END",
754                "S_XMIT",
755        };
756
757        std::cout << name() << " _TGT : " << target_str[r_target_fsm.read()] 
758            << std::endl;
759        std::cout << name() << " _SPI : " << spi_str[r_spi_fsm.read()] 
760            << " clk_counter " << r_spi_clk_counter.read()
761            << " r_spi_bit_count " << r_spi_bit_count.read() 
762            << " r_spi_bsy " << (int)r_spi_bsy.read() << std::endl;
763        std::cout << name() << " _SPI : "
764            << " r_spi_clk " << r_spi_clk.read()
765            << " cpol " << r_ctrl_cpol.read()
766            << " cpha " << r_ctrl_cpha.read()
767            << " r_spi_clk_ignore " << r_spi_clk_ignore.read()
768            << " r_txrx 0x" << std::hex
769            << r_txrx[1].read() << " " << r_txrx[0].read()
770
771            << std::endl;
772        std::cout << name() << "  _INI : " << initiator_str[r_initiator_fsm.read()] 
773          << "  buf = " << std::hex << r_buf_address.read()
774          << "  burst = " << r_burst_word.read() 
775          << "  count = " << r_dma_count.read() 
776          << "  spi_count = " << r_spi_word_count.read() 
777          <<std::endl; 
778}
779
780}} // end namespace
781
782// Local Variables:
783// tab-width: 4
784// c-basic-offset: 4
785// c-file-offsets:((innamespace . 0)(inline-open . 0))
786// indent-tabs-mode: nil
787// End:
788
789// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
790
Note: See TracBrowser for help on using the repository browser.