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

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

r_ctrl_go_bsy is really a flip/flop, explicitely don't reset it in the
VCI FSM. No behavior change, as we do register writes only if r_ctrl_go_bsy
is false anyway.
Print r_ctrl_go_bsy status in print_trace().

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