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

Last change on this file since 1052 was 1052, checked in by alain, 7 years ago

few bugs

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