<commit_before>// this encapsulates the system under emulation.

#include "CardInfo.h"
#include "Cpu2200.h"
#include "Host.h"
#include "IoCardDisk.h"
#include "Scheduler.h"
#include "System2200.h"
#include "SysCfgState.h"
#include "Ui.h"

// ----------------------------------------------------------------------------
// initialize static class members
// ----------------------------------------------------------------------------

// declare the system singleton members
bool                         System2200::m_initialized = false;
std::shared_ptr<Scheduler>   System2200::m_scheduler   = nullptr;
std::shared_ptr<Cpu2200>     System2200::m_cpu         = nullptr;
std::shared_ptr<SysCfgState> System2200::m_config      = nullptr;

System2200::term_state_t     System2200::m_term_state  = RUNNING;
bool                         System2200::m_freeze_emu  = false;
bool                         System2200::m_do_reconfig = false;

// mapping i/o addresses to devices
std::array<System2200::iomap_t,256>              System2200::m_IoMap;
std::array<std::unique_ptr<IoCard>, NUM_IOSLOTS> System2200::m_cardInSlot;
int                                              System2200::m_IoCurSelected;

// speed regulation
int64   System2200::perf_real_ms[100];    // realtime at start of each slice
int     System2200::perf_hist_len;        // number of entries written
int     System2200::perf_hist_ptr;        // next entry to write
bool    System2200::m_regulated_speed;    // try to match speed of real system
bool    System2200::m_firstslice;         // has m_realtimestart been initialized?
int64   System2200::m_realtimestart;      // wall time of when sim started
int     System2200::m_real_seconds;       // real time elapsed

unsigned long System2200::m_simsecs; // number of actual seconds simulated time elapsed

// amount of actual simulated time elapsed, in ms
int64 System2200::m_simtime;

// amount of adjusted simulated time elapsed, in ms because of user events
// (eg, menu selection), sim time is often interrupted and we don't
// actually desire to catch up.  m_simtime is the actual number of
// simulated slices, while this var has been fudged to account for those
// violations of realtime.
int64 System2200::m_adjsimtime;

// ------------------------------------------------------------------------
//  a small logging facility
// ------------------------------------------------------------------------

#include <cstdarg>      // for var args
#include <fstream>

static std::ofstream dbg_ofs;

void
dbglog_open(const std::string &filename)
{
    assert(!dbg_ofs.is_open());     // only one log at a time
    dbg_ofs.open( filename.c_str(), std::ofstream::out | std::ofstream::trunc );
    if (!dbg_ofs.good()) {
        UI_Error("Error opening '%s' for logging.\n", filename.c_str());
        exit(-1);
    }
}

void
dbglog_close()
{
    if (dbg_ofs.is_open()) {
        dbg_ofs.close();
    }
}

void
dbglog(const char *fmt, ...)
{
    char buff[1000];
    va_list args;

    va_start(args, fmt);
    vsnprintf(buff, sizeof(buff), fmt, args);
    va_end(args);

    if (dbg_ofs.good()) {
        dbg_ofs << buff;
        // this is useful if we are getting assert()s, causing
        // the last buffered block to not appear in the log.
        dbg_ofs.flush();
    }
}

// ------------------------------------------------------------------------
// public members
// ------------------------------------------------------------------------

// constructor
System2200::System2200()
{
    if (!m_initialized) {
        // must set this early, otherwise during ramp up, places that
        // invoke System2200 will cause recursion
        m_initialized = true;
#if 0 || defined(_DEBUG)
        dbglog_open("w2200dbg.log");
#endif
        initialize();
    }
}


// destructor
System2200::~System2200()
{
    // this singleton is torn down all the time, but it doesn't mean we can
    // release any state.  cleanup() is the function that cleans house.
}


// initialize singleton
void
System2200::initialize()
{
    // set up IO management
    for(auto &mapentry : m_IoMap) {
        mapentry.slot   = -1;    // unoccupied
        mapentry.ignore = false;
    }
    for(auto &card : m_cardInSlot) {
        card = nullptr;
    }
    m_IoCurSelected = -1;

    // CPU speed regulation
    m_firstslice = true;
    m_simtime    = m_adjsimtime = Host().getTimeMs();
    m_simsecs    = 0;

    m_realtimestart = 0;    // wall time of when sim started
    m_real_seconds  = 0;    // real time elapsed

    m_do_reconfig = false;
    freezeEmu(false);
    setTerminationState(RUNNING);

    m_scheduler = std::make_shared<Scheduler>();

    // attempt to load configuration from saved state
    SysCfgState ini_cfg;
    ini_cfg.loadIni();
    if (!ini_cfg.configOk(false)) {
        UI_Warn(".ini file wasn't usable -- using a default configuration");
        ini_cfg.setDefaults();
    }
    setConfig(ini_cfg);

#if 0
    // intentional error, to see if the leak checker finds it
    int *leaker = new int[100];
    leaker[1] = 123;
#endif
}


// break down any resources currently committed
void
System2200::breakdown_cards(void)
{
    // destroy card instances
    for(auto &card : m_cardInSlot) {
        card = nullptr;
    }

    // clean up mappings
    for(auto &mapentry : m_IoMap) {
        mapentry.slot   = -1;      // unoccupied
        mapentry.ignore = false;   // restore bad I/O warning flags
    }

    if (m_cpu) {
        m_cpu->setDevRdy(true); // nobody is driving, so it floats to 1
    }
}


// build a system according to the spec.
// if a system already exists, tear it down and rebuild it.
void
System2200::setConfig(const SysCfgState &newcfg)
{
    if (!m_config) {
        // first time we don't need to tear anything down
        m_config = std::make_shared<SysCfgState>();
    } else {
        // check if the change is minor, not requiring a teardown
        bool rebuild_required = m_config->needsReboot(newcfg);
        if (!rebuild_required) {
            *m_config = newcfg;  // make new config permanent
            // notify all configured cards about possible new configuration
            for(int slot=0; slot < NUM_IOSLOTS; slot++) {
                if (m_config->isSlotOccupied(slot)) {
                    IoCard::card_t ct = m_config->getSlotCardType(slot);
                    if (CardInfo::isCardConfigurable(ct)) {
                        auto cfg = m_config->getCardConfig(slot);
                        auto card = getInstFromSlot(slot);
                        card->setConfiguration(*cfg);
                    }
                }
            }
            return;
        }

        // the change was major, so delete existing resources
        m_cpu = nullptr;

        // remember which virtual disks are installed
        saveDiskMounts();
        // throw away all existing devices
        breakdown_cards();
    }

    // save the new system configuration state
    *m_config = newcfg;

    // (re)build the CPU
    int ramsize = m_config->getRamKB();
    switch (m_config->getCpuType()) {
        default:
            assert(false);
            // fall through in non-debug build if config type is invalid
        case Cpu2200::CPUTYPE_2200T:
            m_cpu = std::make_shared<Cpu2200t>( this, m_scheduler, ramsize, Cpu2200::CPUTYPE_2200T );
            break;
        case Cpu2200::CPUTYPE_2200B:
            m_cpu = std::make_shared<Cpu2200t>( this, m_scheduler, ramsize, Cpu2200::CPUTYPE_2200B );
            break;
        case Cpu2200::CPUTYPE_2200VP:
            m_cpu = std::make_shared<Cpu2200vp>( this, m_scheduler, ramsize, Cpu2200::CPUTYPE_2200VP );
            break;
    }
    assert(m_cpu);

    // build cards that go into each slot.
    // a hack -- when a display card is made, the crtframe status bar queries
    // to find out how many disk drives are associated with each drive.
    // if the display card is built before the disk controllers, the status
    // bar will be misconfigured.  the hack is to sweep the list twice,
    // skipping CRT's the first time, then doing only CRTs the second time.

    for(int pass=0; pass<2; pass++) {
    for(int slot=0; slot<NUM_IOSLOTS; slot++) {

        if (!m_config->isSlotOccupied(slot)) {
            continue;
        }

        IoCard::card_t cardtype = m_config->getSlotCardType(slot);
        int io_addr             = m_config->getSlotCardAddr(slot) & 0xFF;

        bool display = (cardtype == IoCard::card_t::disp_64x16) ||
                       (cardtype == IoCard::card_t::disp_80x24) ;

        if ((pass==0 && display) || (pass==1 && !display)) {
            continue;
        }

        auto inst = IoCard::makeCard(m_scheduler, m_cpu, cardtype, io_addr,
                                     slot, m_config->getCardConfig(slot).get());
        if (inst == nullptr) {
            // failed to install
            UI_Warn("Configuration problem: failure to create slot %d card instance", slot);
        } else {
            std::vector<int> addresses = inst->getAddresses();
            for(unsigned int n=0; n<addresses.size(); n++) {
                m_IoMap[addresses[n]].slot = slot;
            }
            m_cardInSlot[slot] = std::move(inst);
        }
    }}

    restoreDiskMounts();    // remount disks
}

<commit_msg>make system aware of muxd card<commit_after>// this encapsulates the system under emulation.

#include "CardInfo.h"
#include "Cpu2200.h"
#include "Host.h"
#include "IoCardDisk.h"
#include "Scheduler.h"
#include "System2200.h"
#include "SysCfgState.h"
#include "Ui.h"

// ----------------------------------------------------------------------------
// initialize static class members
// ----------------------------------------------------------------------------

// declare the system singleton members
bool                         System2200::m_initialized = false;
std::shared_ptr<Scheduler>   System2200::m_scheduler   = nullptr;
std::shared_ptr<Cpu2200>     System2200::m_cpu         = nullptr;
std::shared_ptr<SysCfgState> System2200::m_config      = nullptr;

System2200::term_state_t     System2200::m_term_state  = RUNNING;
bool                         System2200::m_freeze_emu  = false;
bool                         System2200::m_do_reconfig = false;

// mapping i/o addresses to devices
std::array<System2200::iomap_t,256>              System2200::m_IoMap;
std::array<std::unique_ptr<IoCard>, NUM_IOSLOTS> System2200::m_cardInSlot;
int                                              System2200::m_IoCurSelected;

// speed regulation
int64   System2200::perf_real_ms[100];    // realtime at start of each slice
int     System2200::perf_hist_len;        // number of entries written
int     System2200::perf_hist_ptr;        // next entry to write
bool    System2200::m_regulated_speed;    // try to match speed of real system
bool    System2200::m_firstslice;         // has m_realtimestart been initialized?
int64   System2200::m_realtimestart;      // wall time of when sim started
int     System2200::m_real_seconds;       // real time elapsed

unsigned long System2200::m_simsecs; // number of actual seconds simulated time elapsed

// amount of actual simulated time elapsed, in ms
int64 System2200::m_simtime;

// amount of adjusted simulated time elapsed, in ms because of user events
// (eg, menu selection), sim time is often interrupted and we don't
// actually desire to catch up.  m_simtime is the actual number of
// simulated slices, while this var has been fudged to account for those
// violations of realtime.
int64 System2200::m_adjsimtime;

// ------------------------------------------------------------------------
//  a small logging facility
// ------------------------------------------------------------------------

#include <cstdarg>      // for var args
#include <fstream>

static std::ofstream dbg_ofs;

void
dbglog_open(const std::string &filename)
{
    assert(!dbg_ofs.is_open());     // only one log at a time
    dbg_ofs.open( filename.c_str(), std::ofstream::out | std::ofstream::trunc );
    if (!dbg_ofs.good()) {
        UI_Error("Error opening '%s' for logging.\n", filename.c_str());
        exit(-1);
    }
}

void
dbglog_close()
{
    if (dbg_ofs.is_open()) {
        dbg_ofs.close();
    }
}

void
dbglog(const char *fmt, ...)
{
    char buff[1000];
    va_list args;

    va_start(args, fmt);
    vsnprintf(buff, sizeof(buff), fmt, args);
    va_end(args);

    if (dbg_ofs.good()) {
        dbg_ofs << buff;
        // this is useful if we are getting assert()s, causing
        // the last buffered block to not appear in the log.
        dbg_ofs.flush();
    }
}

// ------------------------------------------------------------------------
// public members
// ------------------------------------------------------------------------

// constructor
System2200::System2200()
{
    if (!m_initialized) {
        // must set this early, otherwise during ramp up, places that
        // invoke System2200 will cause recursion
        m_initialized = true;
#if 0 || defined(_DEBUG)
        dbglog_open("w2200dbg.log");
#endif
        initialize();
    }
}


// destructor
System2200::~System2200()
{
    // this singleton is torn down all the time, but it doesn't mean we can
    // release any state.  cleanup() is the function that cleans house.
}


// initialize singleton
void
System2200::initialize()
{
    // set up IO management
    for(auto &mapentry : m_IoMap) {
        mapentry.slot   = -1;    // unoccupied
        mapentry.ignore = false;
    }
    for(auto &card : m_cardInSlot) {
        card = nullptr;
    }
    m_IoCurSelected = -1;

    // CPU speed regulation
    m_firstslice = true;
    m_simtime    = m_adjsimtime = Host().getTimeMs();
    m_simsecs    = 0;

    m_realtimestart = 0;    // wall time of when sim started
    m_real_seconds  = 0;    // real time elapsed

    m_do_reconfig = false;
    freezeEmu(false);
    setTerminationState(RUNNING);

    m_scheduler = std::make_shared<Scheduler>();

    // attempt to load configuration from saved state
    SysCfgState ini_cfg;
    ini_cfg.loadIni();
    if (!ini_cfg.configOk(false)) {
        UI_Warn(".ini file wasn't usable -- using a default configuration");
        ini_cfg.setDefaults();
    }
    setConfig(ini_cfg);

#if 0
    // intentional error, to see if the leak checker finds it
    int *leaker = new int[100];
    leaker[1] = 123;
#endif
}


// break down any resources currently committed
void
System2200::breakdown_cards(void)
{
    // destroy card instances
    for(auto &card : m_cardInSlot) {
        card = nullptr;
    }

    // clean up mappings
    for(auto &mapentry : m_IoMap) {
        mapentry.slot   = -1;      // unoccupied
        mapentry.ignore = false;   // restore bad I/O warning flags
    }

    if (m_cpu) {
        m_cpu->setDevRdy(true); // nobody is driving, so it floats to 1
    }
}


// build a system according to the spec.
// if a system already exists, tear it down and rebuild it.
void
System2200::setConfig(const SysCfgState &newcfg)
{
    if (!m_config) {
        // first time we don't need to tear anything down
        m_config = std::make_shared<SysCfgState>();
    } else {
        // check if the change is minor, not requiring a teardown
        bool rebuild_required = m_config->needsReboot(newcfg);
        if (!rebuild_required) {
            *m_config = newcfg;  // make new config permanent
            // notify all configured cards about possible new configuration
            for(int slot=0; slot < NUM_IOSLOTS; slot++) {
                if (m_config->isSlotOccupied(slot)) {
                    IoCard::card_t ct = m_config->getSlotCardType(slot);
                    if (CardInfo::isCardConfigurable(ct)) {
                        auto cfg = m_config->getCardConfig(slot);
                        auto card = getInstFromSlot(slot);
                        card->setConfiguration(*cfg);
                    }
                }
            }
            return;
        }

        // the change was major, so delete existing resources
        m_cpu = nullptr;

        // remember which virtual disks are installed
        saveDiskMounts();
        // throw away all existing devices
        breakdown_cards();
    }

    // save the new system configuration state
    *m_config = newcfg;

    // (re)build the CPU
    int ramsize = m_config->getRamKB();
    switch (m_config->getCpuType()) {
        default:
            assert(false);
            // fall through in non-debug build if config type is invalid
        case Cpu2200::CPUTYPE_2200T:
            m_cpu = std::make_shared<Cpu2200t>( this, m_scheduler, ramsize, Cpu2200::CPUTYPE_2200T );
            break;
        case Cpu2200::CPUTYPE_2200B:
            m_cpu = std::make_shared<Cpu2200t>( this, m_scheduler, ramsize, Cpu2200::CPUTYPE_2200B );
            break;
        case Cpu2200::CPUTYPE_2200VP:
            m_cpu = std::make_shared<Cpu2200vp>( this, m_scheduler, ramsize, Cpu2200::CPUTYPE_2200VP );
            break;
    }
    assert(m_cpu);

    // build cards that go into each slot.
    // a hack -- when a display card is made, the crtframe status bar queries
    // to find out how many disk drives are associated with each drive.
    // if the display card is built before the disk controllers, the status
    // bar will be misconfigured.  the hack is to sweep the list twice,
    // skipping CRT's the first time, then doing only CRTs the second time.

    for(int pass=0; pass<2; pass++) {
    for(int slot=0; slot<NUM_IOSLOTS; slot++) {

        if (!m_config->isSlotOccupied(slot)) {
            continue;
        }

        IoCard::card_t cardtype = m_config->getSlotCardType(slot);
        int io_addr             = m_config->getSlotCardAddr(slot) & 0xFF;

        bool display = (cardtype == IoCard::card_t::disp_64x16)
                    || (cardtype == IoCard::card_t::disp_80x24)
                    || (cardtype == IoCard::card_t::term_mux) ;

        if ((pass==0 && display) || (pass==1 && !display)) {
            continue;
        }

        auto inst = IoCard::makeCard(m_scheduler, m_cpu, cardtype, io_addr,
                                     slot, m_config->getCardConfig(slot).get());
        if (inst == nullptr) {
            // failed to install
            UI_Warn("Configuration problem: failure to create slot %d card instance", slot);
        } else {
            std::vector<int> addresses = inst->getAddresses();
            for(unsigned int n=0; n<addresses.size(); n++) {
                m_IoMap[addresses[n]].slot = slot;
            }
            m_cardInSlot[slot] = std::move(inst);
        }
    }}

    restoreDiskMounts();    // remount disks
}


{'fraction_non_alphanumeric': 0.14967811158798283, 'fraction_numerical': 0.02650214592274678, 'mean_word_length': 1.9945381526104418, 'pattern_counts': {'":': 0, '<': 43, '<?xml version=': 0, '>': 57, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3992976', 'n_tokens_mistral': 5825, 'n_tokens_neox': 5410, 'n_words': 1529}