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

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

Simplify target FSM by doing register read and write in IDLE state,
when we read the request from the VCI port.

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