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

Last change on this file since 592 was 592, checked in by bouyer, 10 years ago
  • report DMA errors
  • minor changes to sync with the VHDL model
File size: 22.3 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                    if (r_dma_error) 
164                        data |= SPI_CTRL_DMA_ERR;
165                    data |= (uint32_t)r_ctrl_char_len.read();
166                    r_rdata = data;
167                    if (write) {
168                        r_ctrl_cpol = ((wdata & SPI_CTRL_CPOL) != 0);
169                        r_ctrl_cpha = ((wdata & SPI_CTRL_CPHA) != 0);
170                        r_ctrl_ie  = ((wdata & SPI_CTRL_IE_EN) != 0);
171                        if (wdata & SPI_CTRL_GO_BSY) 
172                                r_spi_bsy = true;
173                        r_ctrl_char_len = (wdata & SPI_CTRL_CHAR_LEN_MASK);
174#ifdef SOCLIB_MODULE_DEBUG
175                        if ((wdata & SPI_CTRL_GO_BSY) != 0) {
176                            std::cout << name() << " start xfer " << std::dec << (int)r_ctrl_char_len.read() << " data " << std::hex << r_txrx[1] << " " << r_txrx[0] << std::endl;
177                        }
178#endif
179                    } else {
180                        r_irq = r_irq & r_spi_bsy;
181                    }
182                    r_target_fsm = (p_vci_target.cmd.read() == vci_param::CMD_WRITE) ? T_RSP_WRITE : T_RSP_READ;
183                    break;
184                }
185                case SPI_DIVIDER:
186                    r_rdata = r_divider.read();
187                    if (write) {
188#ifdef SOCLIB_MODULE_DEBUG
189                        std::cout << name() << " divider set to " << std::dec << wdata << std::endl;
190#endif
191                        r_divider = wdata;
192                    }
193                    r_target_fsm = (p_vci_target.cmd.read() == vci_param::CMD_WRITE) ? T_RSP_WRITE : T_RSP_READ;
194                    break;
195                case SPI_SS:
196                    r_rdata = r_ss.read();
197                    if (write) {
198                        r_ss = wdata;
199                    }
200                    r_target_fsm = (p_vci_target.cmd.read() == vci_param::CMD_WRITE) ? T_RSP_WRITE : T_RSP_READ;
201                    break;
202                case SPI_DMA_BASE:
203                    r_rdata = r_buf_address.read();
204                    if (write) {
205                        r_buf_address = (r_buf_address & (uint64_t)0xffffffff00000000) | wdata;
206                    }
207                    r_target_fsm = (p_vci_target.cmd.read() == vci_param::CMD_WRITE) ? T_RSP_WRITE : T_RSP_READ;
208                    break;
209                case SPI_DMA_BASEH:
210                    r_rdata = r_buf_address >> 32;
211                    if (write) {
212                        r_buf_address = (r_buf_address & (uint64_t)0x00000000ffffffff) | ((uint64_t)wdata << 32);
213                    }
214                    r_target_fsm = (p_vci_target.cmd.read() == vci_param::CMD_WRITE) ? T_RSP_WRITE : T_RSP_READ;
215                    break;
216                case SPI_DMA_COUNT:
217                    r_rdata = (r_dma_count.read() << m_byte2burst_shift) |
218                        r_read;
219                    if (write) {
220                        r_read = (wdata & 0x1);
221                        r_dma_count = wdata >> m_byte2burst_shift;
222                        r_ctrl_char_len = vci_param::B * 8;
223                    }
224                    r_target_fsm = (p_vci_target.cmd.read() == vci_param::CMD_WRITE) ? T_RSP_WRITE : T_RSP_READ;
225                    break;
226                default:
227                    r_target_fsm = (p_vci_target.cmd.read() == vci_param::CMD_WRITE) ? T_ERROR_WRITE : T_ERROR_READ;
228                    break;
229                }
230            }
231        }
232        break;
233    }
234    ////////////////////
235    case T_RSP_READ:
236    case T_RSP_WRITE:
237    case T_ERROR_READ:
238    case T_ERROR_WRITE:
239        if (p_vci_target.rspack.read() ) {
240            r_target_fsm  = T_IDLE;
241        }
242        break;
243    } // end switch target fsm
244
245
246       
247
248    //////////////////////////////////////////////////////////////////////////////
249    // the SPI FSM controls SPI signals
250    //////////////////////////////////////////////////////////////////////////////
251    if (r_spi_bsy == false)
252        r_spi_done = false;
253    switch (r_spi_fsm) {
254    case S_IDLE:
255        r_spi_clk_counter = r_divider.read();
256        r_spi_clk = 0;
257        r_spi_clk_previous = r_ctrl_cpha;
258        r_spi_clk_ignore = r_ctrl_cpha;
259        r_spi_bit_count = r_ctrl_char_len;
260        if (r_dma_count != 0) {
261                if (r_read.read())
262                        r_spi_fsm = S_DMA_SEND_START;
263                else
264                        r_spi_fsm = S_DMA_RECEIVE;
265        } else if (r_spi_bsy.read() && !r_spi_done.read()) {
266            r_spi_fsm = S_XMIT;
267            r_spi_out = (r_txrx[(r_ctrl_char_len -1)/ 64] >> ((r_ctrl_char_len - 1) % 64)) & (uint64_t)0x0000000000000001ULL;
268        }
269        break;
270    case S_DMA_RECEIVE:
271    {
272        r_spi_clk_counter = r_divider.read();
273        r_spi_clk = 0;
274        r_spi_clk_previous = r_ctrl_cpha;
275        r_spi_clk_ignore = r_ctrl_cpha;
276        r_spi_bit_count = r_ctrl_char_len;
277        if (r_initiator_fsm != M_WRITE_RSP || !p_vci_initiator.rspval.read()) {
278            if (r_dma_fifo_write.rok()) {
279                typename vci_param::data_t v = r_dma_fifo_write.read();
280                r_dma_fifo_write.simple_get();
281                r_txrx[0] = v;
282                r_spi_out = (v >> ((vci_param::B * 8) - 1)) & 0x1;
283                r_spi_fsm = S_XMIT;
284            } else if (r_initiator_fsm == M_WRITE_END) {
285                r_spi_fsm = S_IDLE;
286            }
287        }
288        break;
289    }
290    case S_DMA_SEND_START:
291        r_spi_word_count = (r_dma_count << (m_byte2burst_shift - 2)) - 1;
292        r_spi_out = 1;
293        r_txrx[0] = 0xffffffff;
294        r_spi_fsm = S_XMIT;
295        break;
296    case S_DMA_SEND:
297        r_spi_out = 1;
298        r_spi_clk_counter = r_divider.read();
299        r_spi_clk = 0;
300        r_spi_clk_previous = r_ctrl_cpha;
301        r_spi_clk_ignore = r_ctrl_cpha;
302        r_spi_bit_count = r_ctrl_char_len;
303        if (r_initiator_fsm != M_READ_CMD) {
304            if (r_dma_fifo_read.wok()) {
305                r_dma_fifo_read.simple_put(
306                    (typename vci_param::data_t)r_txrx[0]);
307                r_spi_word_count = r_spi_word_count - 1;
308                r_txrx[0] = 0xffffffff;
309                if ( r_spi_word_count == 0 ) {
310                    r_spi_fsm = S_DMA_SEND_END;
311                } else {
312                    r_spi_fsm = S_XMIT;
313                }
314            }
315        }
316        break;
317    case S_DMA_SEND_END:
318        if (r_initiator_fsm == M_IDLE)
319                r_spi_fsm = S_IDLE;
320        break;
321    case S_XMIT:
322      {
323        bool s_clk_sample;
324        // on clock transition, sample input line, and shift data
325        s_clk_sample = r_spi_clk ^ r_ctrl_cpha;
326        if (!r_spi_clk_ignore) {
327            if (r_spi_clk_previous == 0 && s_clk_sample == 1) {
328                // low to high transition: shift and sample
329                r_txrx[1] = (r_txrx[1] << 1) | (r_txrx[0] >> 63);
330                r_txrx[0] = (r_txrx[0] << 1) | p_spi_miso;
331                r_spi_bit_count = r_spi_bit_count - 1;
332            } else if (r_spi_clk_previous == 1 && s_clk_sample == 0) {
333                // high to low transition: change output, or stop
334                if (r_spi_bit_count == 0) {
335                    if (r_initiator_fsm != M_IDLE) {
336                        if (r_read)
337                            r_spi_fsm = S_DMA_SEND;
338                        else
339                            r_spi_fsm = S_DMA_RECEIVE;
340                    } else {
341                        r_spi_fsm = S_IDLE;
342                        r_irq = r_ctrl_ie;
343                        r_spi_done = true;
344                    }
345#ifdef SOCLIB_MODULE_DEBUG0
346                    std::cout << name() << " end xfer " << std::dec << (int)r_ctrl_char_len.read() << " data " << std::hex << r_txrx[1] << " " << r_txrx[0] << std::endl;
347#endif
348                } else {
349                    r_spi_out = (r_txrx[(r_ctrl_char_len -1)/ 64] >> ((r_ctrl_char_len - 1) % 64)) & (uint64_t)0x0000000000000001ULL;
350                }
351            }
352        }
353        r_spi_clk_previous = s_clk_sample;
354        // generate the SPI clock
355        if (r_spi_clk_counter.read() == 0) {
356            r_spi_clk_counter = r_divider.read();
357            r_spi_clk = !r_spi_clk.read();
358            r_spi_clk_ignore = false;
359        } else {
360            r_spi_clk_counter = r_spi_clk_counter.read() - 1;
361        }
362        break;
363      }
364    }
365    //////////////////////////////////////////////////////////////////////////////
366    // The initiator FSM executes a loop, transfering one burst per iteration.
367    // data comes from or goes to fifos, the other end of the fifos is
368    // feed by or eaten by the SPI fsm.
369    //////////////////////////////////////////////////////////////////////////////
370
371    switch( r_initiator_fsm.read() ) {
372    ////////////
373    case M_IDLE:        // check buffer alignment to compute the number of bursts
374    {
375        if ( r_dma_count != 0 )
376        {
377            // start transfer
378            if ( r_read.read() )    r_initiator_fsm = M_READ_WAIT;
379            else                    r_initiator_fsm = M_WRITE_WAIT;
380        }
381        break;
382    }
383    case M_READ_WAIT:  // wait for the FIFO to be full
384        if (!r_dma_fifo_read.wok()) {
385                r_burst_word = m_words_per_burst - 1;
386                r_initiator_fsm = M_READ_CMD;
387        }
388        break;
389    ////////////////
390    case M_READ_CMD:    // Send a multi-flits VCI WRITE command
391    {
392        if ( p_vci_initiator.cmdack.read() )
393        {
394            if ( r_burst_word == 0 )      // last flit
395            {
396                r_initiator_fsm = M_READ_RSP;
397            }
398            else                    // not the last flit
399            {
400                r_burst_word = r_burst_word.read() - 1;
401            }
402
403            r_dma_fifo_read.simple_get(); // consume one fifo word
404            // compute next word address
405            r_buf_address = r_buf_address.read() + vci_param::B;
406        }
407        break;
408    }
409    ////////////////
410    case M_READ_RSP:    // Wait a single flit VCI WRITE response
411    {
412        if ( p_vci_initiator.rspval.read() )
413        {
414            if ( (p_vci_initiator.rerror.read()&0x1) != 0 ) 
415            {
416                r_burst_word = 0;
417                r_dma_count = 0;
418                r_dma_error = true;
419                r_initiator_fsm = M_IDLE;
420#ifdef SOCLIB_MODULE_DEBUG
421                std::cout << "vci_bd M_READ_ERROR" << std::endl;
422#endif
423            }
424            else if ( r_spi_fsm == S_DMA_SEND_END ) // last burst
425            {
426                r_dma_count = 0;
427                r_initiator_fsm = M_IDLE;
428                r_dma_error = false;
429#ifdef SOCLIB_MODULE_DEBUG
430                std::cout << "vci_bd M_READ_SUCCESS" << std::endl;
431#endif
432            }
433            else // keep on reading
434            {
435                r_dma_count = r_dma_count - 1;
436                r_initiator_fsm  = M_READ_WAIT;
437            }
438        }
439        break;
440    }
441    ///////////////////
442    case M_WRITE_WAIT:  // wait for the FIFO to be empty
443        if (!r_dma_fifo_write.rok()) {
444            r_burst_word = m_words_per_burst - 1;
445            r_dma_count = r_dma_count - 1;
446            r_initiator_fsm = M_WRITE_CMD;
447        }
448        break;
449    /////////////////
450    case M_WRITE_CMD:   // This is actually a single flit VCI READ command
451    {
452        if ( p_vci_initiator.cmdack.read() ) r_initiator_fsm = M_WRITE_RSP;
453        break;
454    }
455    /////////////////
456    case M_WRITE_RSP:   // This is actually a multi-words VCI READ response
457    {
458        if ( p_vci_initiator.rspval.read() )
459        {
460            typename vci_param::data_t v = p_vci_initiator.rdata.read();
461            typename vci_param::data_t f = 0;
462            // byte-swap
463            for (int i = 0; i < (vci_param::B * 8); i += 8) {
464                f |= ((v >> i) & 0xff) << ((vci_param::B * 8) - 8 - i);
465            }
466            r_dma_fifo_write.simple_put(f);
467            r_burst_word = r_burst_word.read() - 1;
468            if ( p_vci_initiator.reop.read() )  // last flit of the burst
469            {
470                r_buf_address = r_buf_address.read() + m_burst_size;
471
472                if( (p_vci_initiator.rerror.read()&0x1) != 0 ) 
473                {
474                    r_dma_count = 0;
475                    r_dma_error = 1;
476                    r_initiator_fsm = M_WRITE_END;
477#ifdef SOCLIB_MODULE_DEBUG
478                    std::cout << "vci_bd M_WRITE_ERROR" << std::endl;
479#endif
480                }
481                else if ( r_dma_count.read() == 0) // last burst
482                {
483                    r_dma_error = 0;
484                    r_initiator_fsm  = M_WRITE_END;
485                }
486                else                                      // not the last burst
487                {
488                    r_initiator_fsm = M_WRITE_WAIT;
489                }
490            }
491        }
492        break;
493    }
494    /////////////////
495    case M_WRITE_END:   // wait for the write to be complete
496    {
497        if (r_spi_fsm == S_IDLE) { // write complete
498            r_initiator_fsm  = M_IDLE;
499        }
500        break;
501    }
502  } // end switch r_initiator_fsm
503}  // end transition
504
505//////////////////////
506tmpl(void)::genMoore()
507{
508    // p_vci_target port   
509    p_vci_target.rsrcid = (sc_dt::sc_uint<vci_param::S>)r_srcid.read();
510    p_vci_target.rtrdid = (sc_dt::sc_uint<vci_param::T>)r_trdid.read();
511    p_vci_target.rpktid = (sc_dt::sc_uint<vci_param::P>)r_pktid.read();
512    p_vci_target.reop   = true;
513
514    switch(r_target_fsm) {
515    case T_IDLE:
516        p_vci_target.cmdack = true;
517        p_vci_target.rspval = false;
518        p_vci_target.rdata  = 0;
519        break;
520    case T_RSP_READ:
521        p_vci_target.cmdack = false;
522        p_vci_target.rspval = true;
523        p_vci_target.rdata = r_rdata;
524        p_vci_target.rerror = VCI_READ_OK;
525        break;
526    case T_RSP_WRITE:
527        p_vci_target.cmdack = false;
528        p_vci_target.rspval = true;
529        p_vci_target.rdata  = 0;
530        p_vci_target.rerror = VCI_WRITE_OK;
531        break;
532    case T_ERROR_READ:
533        p_vci_target.cmdack = false;
534        p_vci_target.rspval = true;
535        p_vci_target.rdata  = 0;
536        p_vci_target.rerror = VCI_READ_ERROR;
537        break;
538    case T_ERROR_WRITE:
539        p_vci_target.cmdack = false;
540        p_vci_target.rspval = true;
541        p_vci_target.rdata  = 0;
542        p_vci_target.rerror = VCI_WRITE_ERROR;
543        break;
544    } // end switch target fsm
545
546    // p_vci_initiator port
547    p_vci_initiator.srcid  = (sc_dt::sc_uint<vci_param::S>)m_srcid;
548    p_vci_initiator.trdid  = 0;
549    p_vci_initiator.contig = true;
550    p_vci_initiator.cons   = false;
551    p_vci_initiator.wrap   = false;
552    p_vci_initiator.cfixed = false;
553    p_vci_initiator.clen   = 0;
554
555    switch (r_initiator_fsm) {
556    case M_WRITE_CMD:           // It is actually a single flit VCI read command
557        p_vci_initiator.rspack  = false;
558        p_vci_initiator.cmdval  = true;
559        p_vci_initiator.address = (sc_dt::sc_uint<vci_param::N>)r_buf_address.read();
560        p_vci_initiator.cmd     = vci_param::CMD_READ;
561        p_vci_initiator.pktid   = TYPE_READ_DATA_UNC; 
562        p_vci_initiator.wdata   = 0;
563        p_vci_initiator.be      = 0;
564        p_vci_initiator.plen    = (sc_dt::sc_uint<vci_param::K>)(m_burst_size);
565        p_vci_initiator.eop     = true;
566        break;
567    case M_READ_CMD:            // It is actually a multi-words VCI WRITE command
568    {
569        typename vci_param::data_t v = 0;
570        typename vci_param::data_t f;
571        p_vci_initiator.rspack  = false;
572        p_vci_initiator.cmdval  = true;
573        p_vci_initiator.address = (sc_dt::sc_uint<vci_param::N>)r_buf_address.read();
574        p_vci_initiator.cmd     = vci_param::CMD_WRITE;
575        p_vci_initiator.pktid   = TYPE_WRITE;
576        p_vci_initiator.plen    = (sc_dt::sc_uint<vci_param::K>)(m_burst_size);
577        f = r_dma_fifo_read.read();
578        // byte-swap
579        for (int i = 0; i < (vci_param::B * 8); i += 8) {
580                v |= ((f >> i) & 0xff) << ((vci_param::B * 8) - 8 - i);
581        }
582        p_vci_initiator.wdata = v;
583        p_vci_initiator.eop   = ( r_burst_word.read() == 0);
584        if (vci_param::B == 8)
585        {
586            p_vci_initiator.be    = 0xFF;
587        }
588        else
589        {
590            p_vci_initiator.be    = 0xF;
591        }
592        break;
593    }
594    case M_READ_RSP:
595    case M_WRITE_RSP:
596        p_vci_initiator.rspack  = true;
597        p_vci_initiator.cmdval  = false;
598        break;
599    default:
600        p_vci_initiator.rspack  = false;
601        p_vci_initiator.cmdval  = false;
602        break;
603    }
604
605    // SPI signals
606    p_spi_ss = ((r_ss & 0x1) == 0);
607    switch(r_spi_fsm) {
608    default:
609        p_spi_mosi = r_spi_out;
610        p_spi_clk = 0;
611        break;
612    case S_XMIT:
613      {
614        bool s_clk_sample = r_spi_clk ^ r_ctrl_cpha;
615        p_spi_clk = r_spi_clk ^ r_ctrl_cpol;
616        if (s_clk_sample == 0) {
617            // clock low: get data directly from shift register
618            // as r_spi_out may be delayed by one clock cycle
619            p_spi_mosi = (r_txrx[(r_ctrl_char_len -1)/ 64] >> ((r_ctrl_char_len - 1) % 64)) & (uint64_t)0x0000000000000001ULL;
620        } else {
621            // clock high: get data from saved value, as the shift register
622            // may have changed
623            p_spi_mosi = r_spi_out;
624        }
625        break;
626      }
627    }
628
629    // IRQ signal
630    p_irq = r_irq;
631} // end GenMoore()
632
633//////////////////////////////////////////////////////////////////////////////
634tmpl(/**/)::VciSpi( sc_core::sc_module_name           name, 
635                                const soclib::common::MappingTable   &mt,
636                                const soclib::common::IntTab     &srcid,
637                                const soclib::common::IntTab     &tgtid,
638                                const uint32_t                 burst_size)
639
640: caba::BaseModule(name),
641        m_seglist(mt.getSegmentList(tgtid)),
642        m_srcid(mt.indexForId(srcid)),
643        m_burst_size(burst_size),
644        m_words_per_burst(burst_size / vci_param::B),
645        m_byte2burst_shift(soclib::common::uint32_log2(burst_size)),
646        p_clk("p_clk"),
647        p_resetn("p_resetn"),
648        p_vci_initiator("p_vci_initiator"),
649        p_vci_target("p_vci_target"),
650        p_irq("p_irq"),
651        p_spi_ss("p_spi_ss"),
652        p_spi_clk("p_spi_clk"),
653        p_spi_mosi("p_spi_mosi"),
654        p_spi_miso("p_spi_miso"),
655
656        r_dma_fifo_read("r_dma_fifo_read", burst_size / vci_param::B), // one cache line
657        r_dma_fifo_write("r_dma_fifo_read", burst_size / vci_param::B) // one cache line
658{
659    std::cout << "  - Building VciSpi " << name << std::endl;
660
661        SC_METHOD(transition);
662    dont_initialize();
663    sensitive << p_clk.pos();
664
665        SC_METHOD(genMoore);
666    dont_initialize();
667    sensitive << p_clk.neg();
668
669    size_t nbsegs = 0;
670    std::list<soclib::common::Segment>::iterator seg;
671    for ( seg = m_seglist.begin() ; seg != m_seglist.end() ; seg++ ) 
672    {
673        nbsegs++;
674       
675            if ( (seg->baseAddress() & 0x0000003F) != 0 ) 
676            {
677                    std::cout << "Error in component VciSpi : " << name
678                              << "The base address of segment " << seg->name()
679                      << " must be multiple of 64 bytes" << std::endl;
680                    exit(1);
681            }
682            if ( seg->size() < 64 ) 
683            {
684                    std::cout << "Error in component VciSpi : " << name
685                          << "The size of segment " << seg->name()
686                      << " cannot be smaller than 64 bytes" << std::endl;
687                    exit(1);
688            }
689        std::cout << "    => segment " << seg->name()
690                  << " / base = " << std::hex << seg->baseAddress()
691                  << " / size = " << seg->size() << std::endl; 
692    }
693
694    if( nbsegs == 0 )
695    {
696                std::cout << "Error in component VciSpi : " << name
697                          << " No segment allocated" << std::endl;
698                exit(1);
699    }
700
701    if( (burst_size != 8 ) && 
702                (burst_size != 16) && 
703                (burst_size != 32) && 
704                (burst_size != 64) )
705        {
706                std::cout << "Error in component VciSpi : " << name
707                          << " The burst size must be 8, 16, 32 or 64 bytes" << std::endl;
708                exit(1);
709        }
710
711        if ( (vci_param::B != 4) and (vci_param::B != 8) )
712        {
713                std::cout << "Error in component VciSpi : " << name           
714                          << " The VCI data fields must have 32 bits or 64 bits" << std::endl;
715                exit(1);
716        }
717
718} // end constructor
719
720tmpl(/**/)::~VciSpi()
721{
722}
723
724
725//////////////////////////
726tmpl(void)::print_trace()
727{
728        const char* initiator_str[] = 
729    {
730                "M_IDLE",
731
732                "M_READ_WAIT",
733                "M_READ_CMD",
734                "M_READ_RSP",
735
736                "M_WRITE_WAIT",
737                "M_WRITE_CMD",
738                "M_WRITE_RSP",
739                "M_WRITE_END",
740        };
741        const char* target_str[] = 
742        {
743                "T_IDLE",
744                "T_RSP_READ",
745                "T_RSP_WRITE",
746                "T_ERROR_READ",
747                "T_ERROR_WRITE",
748        };
749        const char* spi_str[] = 
750        {
751                "S_IDLE",
752                "S_DMA_RECEIVE",
753                "S_DMA_SEND_START",
754                "S_DMA_SEND",
755                "S_DMA_SEND_END",
756                "S_XMIT",
757        };
758
759        std::cout << name() << " _TGT : " << target_str[r_target_fsm.read()] 
760            << std::endl;
761        std::cout << name() << " _SPI : " << spi_str[r_spi_fsm.read()] 
762            << " clk_counter " << r_spi_clk_counter.read()
763            << " r_spi_bit_count " << r_spi_bit_count.read() 
764            << " r_spi_bsy " << (int)r_spi_bsy.read() << std::endl;
765        std::cout << name() << " _SPI : "
766            << " r_spi_clk " << r_spi_clk.read()
767            << " cpol " << r_ctrl_cpol.read()
768            << " cpha " << r_ctrl_cpha.read()
769            << " r_spi_clk_ignore " << r_spi_clk_ignore.read()
770            << " r_txrx 0x" << std::hex
771            << r_txrx[1].read() << " " << r_txrx[0].read()
772
773            << std::endl;
774        std::cout << name() << "  _INI : " << initiator_str[r_initiator_fsm.read()] 
775          << "  buf = " << std::hex << r_buf_address.read()
776          << "  burst = " << r_burst_word.read() 
777          << "  count = " << r_dma_count.read() 
778          << "  spi_count = " << r_spi_word_count.read() 
779          <<std::endl; 
780}
781
782}} // end namespace
783
784// Local Variables:
785// tab-width: 4
786// c-basic-offset: 4
787// c-file-offsets:((innamespace . 0)(inline-open . 0))
788// indent-tabs-mode: nil
789// End:
790
791// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
792
Note: See TracBrowser for help on using the repository browser.