diff --git a/src/dev/lupio/LupioTTY.py b/src/dev/lupio/LupioTTY.py new file mode 100644 index 0000000000..972311fea7 --- /dev/null +++ b/src/dev/lupio/LupioTTY.py @@ -0,0 +1,40 @@ +# Copyright (c) 2021 The Regents of the University of California +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from m5.params import Param +from m5.proxy import Parent + +from m5.objects.Device import BasicPioDevice + +class LupioTTY(BasicPioDevice): + type = 'LupioTTY' + cxx_class = 'gem5::LupioTTY' + cxx_header = "dev/lupio/lupio_tty.hh" + terminal = Param.SerialDevice(Parent.any, "The terminal") + pio_size = Param.Addr(0x1000, "PIO size") + platform = Param.Platform(Parent.any, + "Platform this device is part of.") + int_id = Param.Int("Interrupt ID for the PIC to use") diff --git a/src/dev/lupio/SConscript b/src/dev/lupio/SConscript index 775412ca0c..c5d6b8f87a 100644 --- a/src/dev/lupio/SConscript +++ b/src/dev/lupio/SConscript @@ -26,11 +26,14 @@ Import('*') -SimObject('LupioRTC.py', tags='riscv isa') SimObject('LupioRNG.py', tags='riscv isa') +SimObject('LupioRTC.py', tags='riscv isa') +SimObject('LupioTTY.py', tags='riscv isa') DebugFlag('LupioRNG') DebugFlag('LupioRTC') +DebugFlag('LupioTTY') -Source('lupio_rtc.cc', tags='riscv isa') Source('lupio_rng.cc', tags='riscv isa') +Source('lupio_rtc.cc', tags='riscv isa') +Source('lupio_tty.cc', tags='riscv isa') diff --git a/src/dev/lupio/lupio_tty.cc b/src/dev/lupio/lupio_tty.cc new file mode 100644 index 0000000000..0989947abe --- /dev/null +++ b/src/dev/lupio/lupio_tty.cc @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2021 The Regents of the University of California + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "dev/lupio/lupio_tty.hh" + +#include "base/trace.hh" +#include "debug/LupioTTY.hh" +#include "dev/platform.hh" +#include "mem/packet_access.hh" +#include "params/LupioTTY.hh" + +#define LUPIO_TTY_INVAL 0x80000000 + +/* Same fields for CTRL and STAT registers */ +#define LUPIO_TTY_WBIT (1 << 0) +#define LUPIO_TTY_RBIT (1 << 1) + +namespace gem5 +{ + +LupioTTY::LupioTTY(const Params ¶ms) + : BasicPioDevice(params, params.pio_size), + writChar(-1), readChar(-1), writIntrEn(false), readIntrEn(false), + terminal(params.terminal), platform(params.platform) +{ + // setup serial device callbacks + terminal->regInterfaceCallback([this]() { dataAvailable(); }); +} + +void +LupioTTY::lupioTTYUpdateIRQ() +{ + unsigned int irq; + + irq = (writIntrEn && writChar != -1) + || (readIntrEn && readChar != -1); + + if (irq) { + DPRINTF(LupioTTY, "LupioTTY InterEvent, interrupting\n"); + platform->postConsoleInt(); + } else { + DPRINTF(LupioTTY, "LupioTTY InterEvent, not interrupting\n"); + platform->clearConsoleInt(); + } +} + +void +LupioTTY::dataAvailable() +{ + gem5_assert(terminal->dataAvailable()); + + // prevent from overwritting an unread character + if (readChar != -1) { + fprintf(stderr, "Dropping characters\n"); + } else { + // read data from the terminal + readChar = terminal->readData(); + lupioTTYUpdateIRQ(); + } +} + +uint64_t +LupioTTY::lupioTTYRead(uint8_t addr) +{ + uint32_t ret = LUPIO_TTY_INVAL; + + switch (addr >> 2) { + case LUPIO_TTY_WRIT: + DPRINTF(LupioTTY, "Accessing LUPIO_TTY_WRIT\n"); + if (writChar != -1) { + ret = writChar; + writChar = -1; + lupioTTYUpdateIRQ(); + } + break; + case LUPIO_TTY_READ: + DPRINTF(LupioTTY, "Accessing LUPIO_TTY_READ\n"); + if (readChar != -1) { + // return new character + ret = readChar; + readChar = -1; + lupioTTYUpdateIRQ(); + } + break; + case LUPIO_TTY_CTRL: + DPRINTF(LupioTTY, "Accessing LUPIO_TTY_CTRL\n"); + ret = 0; + if (writIntrEn) { + ret |= LUPIO_TTY_WBIT; + } + if (readIntrEn) { + ret |= LUPIO_TTY_RBIT; + } + break; + case LUPIO_TTY_STAT: + DPRINTF(LupioTTY, "Accessing LUPIO_TTY_STAT\n"); + // always ready to write + ret = LUPIO_TTY_WBIT; + // ready to read if unread character available + if (readChar != -1) { + ret |= LUPIO_TTY_RBIT; + } + break; + default: + panic("Unexpected read to the LupioTTY device at address %d!", + addr); + break; + } + + return ret; +} + +void +LupioTTY::lupioTTYWrite(uint8_t addr, uint64_t val64) +{ + uint32_t val = val64; + uint8_t c = val; + + switch (addr >> 2) { + case LUPIO_TTY_WRIT: + DPRINTF(LupioTTY, "Accessing Write: LUPIO_TTY_WRIT: %d\n", c); + // write data to terminal + terminal->writeData(c); + writChar = c; + lupioTTYUpdateIRQ(); + break; + case LUPIO_TTY_CTRL: + // set interrupt enable bits + DPRINTF(LupioTTY, "Accessing LUPIO_TTY_CTRL\n"); + writIntrEn = val & LUPIO_TTY_WBIT; + readIntrEn = val & LUPIO_TTY_RBIT; + lupioTTYUpdateIRQ(); + break; + default: + panic("Unexpected write to the LupioTTY device at address %d!", + addr); + break; + } +} + +Tick +LupioTTY::read(PacketPtr pkt) +{ + Addr tty_addr = pkt->getAddr() - pioAddr; + + DPRINTF(LupioTTY, + "Read request - addr: %#x, size: %#x\n", tty_addr, pkt->getSize()); + + uint64_t val = lupioTTYRead(tty_addr); + pkt->setUintX(val, byteOrder); + + pkt->makeResponse(); + + return pioDelay; +} + +Tick +LupioTTY::write(PacketPtr pkt) +{ + Addr tty_addr = pkt->getAddr() - pioAddr; + DPRINTF(LupioTTY, + "Write request - addr: %#x pktAddr: %#x value: %c\n", tty_addr, + pkt->getAddr(), pkt->getUintX(byteOrder)); + + lupioTTYWrite(tty_addr, pkt->getUintX(byteOrder)); + + pkt->makeResponse(); + + return pioDelay; +} + +} // namespace gem5 diff --git a/src/dev/lupio/lupio_tty.hh b/src/dev/lupio/lupio_tty.hh new file mode 100644 index 0000000000..1124193419 --- /dev/null +++ b/src/dev/lupio/lupio_tty.hh @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2021 The Regents of the University of California + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __LUPIO_TTY_HH__ +#define __LUPIO_TTY_HH__ + +#include "dev/io_device.hh" +#include "dev/platform.hh" +#include "dev/serial/serial.hh" +#include "params/LupioTTY.hh" + +namespace gem5 +{ + +class Terminal; +/** + * LupioTTY: + * The LupioTTY is a virtual terminal device that can both transmit characters + * to a screen, as well as receive characters input from a keyboard. + */ +class LupioTTY : public BasicPioDevice +{ + private: + // Register map + enum + { + LUPIO_TTY_WRIT, + LUPIO_TTY_READ, + LUPIO_TTY_CTRL, + LUPIO_TTY_STAT, + + // Max offset + LUPIO_TTY_MAX, + }; + + // Internal registers + int8_t writChar; + int8_t readChar; + bool writIntrEn; + bool readIntrEn; + + uint64_t lupioTTYRead(const uint8_t addr); + void lupioTTYWrite(const uint8_t addr, uint64_t c); + /** + * IRQ management + */ + void lupioTTYUpdateIRQ(); + + SerialDevice *terminal; + const ByteOrder byteOrder = ByteOrder::little; + Platform *platform; + + public: + PARAMS(LupioTTY); + LupioTTY(const Params &p); + + /** + * Inform the LupIO-TTY there is data available + */ + void dataAvailable(); + + /** + * Implement BasicPioDevice virtual functions + */ + Tick read(PacketPtr pkt) override; + Tick write(PacketPtr pkt) override; +}; + +} //namespace gem5 + +#endif // __LUPIO_TTY_HH__