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, 13 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.