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

Last change on this file since 667 was 595, checked in by bouyer, 11 years ago

Sync with VHDL, make IRQ work for DMA.

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