source: trunk/modules/vci_tty_tsar/caba/source/src/vci_tty_tsar.cpp

Last change on this file was 1054, checked in by alain, 7 years ago

Introduce the "vci_tty_tsar" component, that has two maskable interrups
(TX_IRQ and RX_IRQ) per channel.

File size: 10.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, Asim
24 *         Nicolas Pouillon <nipo@ssji.net>, 2007
25 *
26 * Maintainers: alain
27 */
28
29#include "../include/vci_tty_tsar.h"
30#include "tty.h"
31
32#include <stdarg.h>
33
34namespace soclib {
35namespace caba {
36
37#define tmpl(t) template<typename vci_param> t VciTtyTsar<vci_param>
38
39////////////////////////
40tmpl(void)::transition()
41{
42        if (!p_resetn) 
43    {
44                r_fsm_state  = IDLE;
45        for( size_t channel = 0 ; channel < m_term.size() ; channel++ ) 
46        {
47            r_rx_irq_enable[channel] = 0;
48            r_tx_irq_enable[channel] = 0;
49        }
50                return;
51        }
52
53    switch ( r_fsm_state.read() )
54    {
55        //////////
56        case IDLE:   // waiting a VCI command
57        {
58            if ( not p_vci.cmdval.read() ) break;
59
60            vci_addr_t address = p_vci.address.read();
61            size_t     cell      = (size_t)((address & 0xFFF)>>2);
62            size_t     reg       = cell % TTY_SPAN;
63            size_t     channel   = cell / TTY_SPAN;
64            bool       seg_error = true;
65
66            r_srcid = p_vci.srcid.read();
67            r_trdid = p_vci.trdid.read();
68            r_pktid = p_vci.pktid.read();
69
70            std::list<soclib::common::Segment>::iterator seg;
71            for ( seg = m_seglist.begin() ; seg != m_seglist.end() ; seg++ )
72            {
73                if ( seg->contains( address ) and p_vci.eop.read() )
74                {
75                    seg_error   = false;
76                    break;
77                }
78            }
79
80            /////////////////////////////////////////////////////////
81            if      ( not seg_error and            // write char
82                      (p_vci.cmd.read() == vci_param::CMD_WRITE) and
83                      (reg == TTY_WRITE ) and
84                      channel < m_term.size() )
85            {
86                // suppose an infinite write buffer (never full)
87                m_term[channel]->putc( p_vci.wdata.read() );
88
89                r_fsm_state = RSP_WRITE;
90            }     
91            /////////////////////////////////////////////////////////
92            else if ( not seg_error and            // read char
93                      (p_vci.cmd.read() == vci_param::CMD_READ) and
94                      (reg == TTY_READ) and
95                      channel < m_term.size() )
96            {
97                vci_data_t  byte = m_term[channel]->getc();
98
99                // skip CR code
100                if ( byte == 0x0d ) r_rdata = m_term[channel]->getc();
101                else                r_rdata = byte;
102
103                r_fsm_state = RSP_READ;
104            }
105            /////////////////////////////////////////////////////////
106            else if ( not seg_error and            // read status
107                      (p_vci.cmd.read() == vci_param::CMD_READ) and
108                      (reg == TTY_STATUS) and
109                      channel < m_term.size() )
110            {
111                // read buffer can be empty    => bit 0 can be 0 or 1
112                // write buffer is never full  => bit 1 is always 0
113               
114                r_rdata     = m_term[channel]->hasData();
115                r_fsm_state = RSP_READ;
116            }
117            /////////////////////////////////////////////////////////
118            else if ( not seg_error and            // set / reset rx_irq
119                      (p_vci.cmd.read() == vci_param::CMD_WRITE) and
120                      (reg == TTY_RX_IRQ_ENABLE) and
121                      channel < m_term.size() )
122            {
123                r_rx_irq_enable[channel] = p_vci.wdata.read();
124                r_fsm_state = RSP_WRITE;
125            }
126            /////////////////////////////////////////////////////////
127            else if ( not seg_error and            // set / reset tx_irq
128                      (p_vci.cmd.read() == vci_param::CMD_WRITE) and
129                      (reg == TTY_TX_IRQ_ENABLE) and
130                      channel < m_term.size() )
131            {
132                r_tx_irq_enable[channel] = p_vci.wdata.read();
133                r_fsm_state = RSP_WRITE;
134            }
135            /////////////////////////////////////////////////////////
136            else if ( p_vci.eop.read() )
137            {
138                r_fsm_state = RSP_ERROR;
139            }
140            break;
141        }
142        ///////////////
143        case RSP_ERROR:   // return an error response
144        case RSP_READ:    // return a valid read response
145        case RSP_WRITE:   // return a valid write response
146        {
147            if ( p_vci.rspack.read() ) r_fsm_state = IDLE;
148            break;
149        }
150    }  // end switch r_fsm_state
151}
152
153//////////////////////
154tmpl(void)::genMoore()
155{
156    if ( r_fsm_state.read() == IDLE )
157    {
158        p_vci.cmdack  = true;
159        p_vci.rspval  = false;
160        p_vci.rdata   = 0;
161        p_vci.rsrcid  = 0;
162        p_vci.rtrdid  = 0;
163        p_vci.rpktid  = 0;
164        p_vci.rerror  = vci_param::ERR_NORMAL;
165        p_vci.reop    = true;
166    }
167    else if ( r_fsm_state.read() == RSP_WRITE )
168    {
169        p_vci.cmdack  = false;
170        p_vci.rspval  = true;
171        p_vci.rdata   = 0;
172        p_vci.rsrcid  = r_srcid.read();
173        p_vci.rtrdid  = r_trdid.read();
174        p_vci.rpktid  = r_pktid.read();
175        p_vci.rerror  = vci_param::ERR_NORMAL;
176        p_vci.reop    = true;
177    }
178    else if ( r_fsm_state.read() == RSP_READ )
179    {
180        p_vci.cmdack  = false;
181        p_vci.rspval  = true;
182        p_vci.rdata   = r_rdata.read();
183        p_vci.rsrcid  = r_srcid.read();
184        p_vci.rtrdid  = r_trdid.read();
185        p_vci.rpktid  = r_pktid.read();
186        p_vci.rerror  = vci_param::ERR_NORMAL;
187        p_vci.reop    = true;
188    }
189    else if ( r_fsm_state.read() == RSP_ERROR )
190    {
191        p_vci.cmdack  = false;
192        p_vci.rspval  = true;
193        p_vci.rdata   = 0;
194        p_vci.rsrcid  = r_srcid.read();
195        p_vci.rtrdid  = r_trdid.read();
196        p_vci.rpktid  = r_pktid.read();
197        p_vci.rerror  = vci_param::ERR_GENERAL_DATA_ERROR;
198        p_vci.reop    = true;
199    }
200
201    for ( size_t channel = 0; channel < m_term.size(); channel++ )
202    {
203        // activate RX_IRQ if RX buffer not empty and RX_IRQ enable
204        p_irq_rx[channel] = (bool)m_term[channel]->hasData() && 
205                            r_rx_irq_enable[channel].read();
206
207        // activate TX_IRQ if TX_IRQ enable ( TX buffer is never full )
208        p_irq_tx[channel] = r_tx_irq_enable[channel].read();
209    }
210}
211
212///////////////////////////////////////////////////////
213tmpl(void)::init(const std::vector<std::string> &names)
214{
215    size_t channel = 0;
216   
217    for ( std::vector<std::string>::const_iterator i = names.begin();
218          i != names.end();
219          ++i )
220    {
221        assert( (channel < 32) and "VCI_TTY_TSAR ERROR : no more than 32 channels");
222                m_term.push_back(soclib::common::allocateTty(*i));
223        channel++;
224    }
225
226        p_irq_rx = new sc_out<bool>[m_term.size()];
227        p_irq_tx = new sc_out<bool>[m_term.size()];
228   
229        SC_METHOD(transition);
230        dont_initialize();
231        sensitive << p_clk.pos();
232
233        SC_METHOD(genMoore);
234        dont_initialize();
235        sensitive << p_clk.neg();
236}
237
238/////////////////////////////////////////////////
239tmpl(/**/)::VciTtyTsar( sc_module_name     name,
240                        const IntTab       &index,
241                        const MappingTable &mt,
242                        const char *first_name, ...)
243    : soclib::caba::BaseModule(name),
244      p_clk("clk"),
245      p_resetn("resetn"),
246      p_vci("vci"),
247      m_seglist(mt.getSegmentList(index))
248{
249    std::cout << "  - Building VciTtyTsar " << name << std::endl;
250
251    std::list<soclib::common::Segment>::iterator seg;
252    for ( seg = m_seglist.begin() ; seg != m_seglist.end() ; seg++ )
253    {
254        std::cout << "    => segment " << seg->name()
255                  << " / base = " << std::hex << seg->baseAddress()
256                  << " / size = " << seg->size() << std::endl; 
257    }
258
259        va_list va_tty;
260
261        va_start (va_tty, first_name);
262    std::vector<std::string> args;
263        const char *cur_tty = first_name;
264        while (cur_tty) 
265    {
266        args.push_back(cur_tty);
267
268                cur_tty = va_arg( va_tty, char * );
269        }
270        va_end( va_tty );
271
272    init(args);
273}
274
275/////////////////////////////////////////////////////////////
276tmpl(/**/)::VciTtyTsar( sc_module_name                  name,
277                        const IntTab                    &index,
278                        const MappingTable              &mt,
279                        const std::vector<std::string>  &names )
280    : soclib::caba::BaseModule(name),
281      p_clk("clk"),
282      p_resetn("resetn"),
283      p_vci("vci"),
284      m_seglist(mt.getSegmentList(index))
285{
286    std::cout << "  - Building VciMultiTTy " << name << std::endl;
287
288    std::list<soclib::common::Segment>::iterator seg;
289    for ( seg = m_seglist.begin() ; seg != m_seglist.end() ; seg++ )
290    {
291        std::cout << "    => segment " << seg->name()
292                  << " / base = " << std::hex << seg->baseAddress()
293                  << " / size = " << seg->size() << std::endl; 
294    }
295
296    init(names);
297}
298
299/////////////////////////
300tmpl(/**/)::~VciTtyTsar()
301{
302        for (unsigned int i=0; i<m_term.size(); i++ )
303        delete m_term[i];
304
305        delete[] p_irq_rx;
306        delete[] p_irq_tx;
307}
308
309/////////////////////////////////////////
310tmpl(void)::print_trace( size_t channel )
311{
312    const char* state_str[] = { "IDLE",
313                                "RSP_WRITE",
314                                "RSP_READ",
315                                "RSP_ERROR", };
316
317    std::cout << "MULTI_TTY " << name()
318              << " : fsm = " << state_str[r_fsm_state.read()] << std::dec
319              << " / RX_IRQ[" << channel << "] = " << r_rx_irq_enable[channel].read()
320              << " / TX_IRQ[" << channel << "] = " << r_tx_irq_enable[channel].read()
321              << std::endl; 
322}
323
324}}
325
326// Local Variables:
327// tab-width: 4
328// c-basic-offset: 4
329// c-file-offsets:((innamespace . 0)(inline-open . 0))
330// indent-tabs-mode: nil
331// End:
332
333// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
334
Note: See TracBrowser for help on using the repository browser.