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

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

Remove Auto Slave Select feature

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