diff --git a/Makefile b/Makefile index fc88e53..92d6c9a 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ CXXFLAGS=-g -std=c++11 all: v6502 -v6502: v6502.o cpu.o nodes.o trans.o SegmentCache.o TransNetwork.o +v6502: v6502.o cpu.o nodes.o trans.o SegmentCache.o TransNetwork.o Trace.o g++ $^ -o $@ v6502.o: v6502.cpp cpu.h addressbus.h TransNetwork.h @@ -17,6 +17,8 @@ SegmentCache.o: SegmentCache.cpp SegmentCache.h TransNetwork.o: TransNetwork.cpp TransNetwork.h trans.h +Trace.o: Trace.cpp Trace.h SegmentCache.h + clean: -rm *.o -rm v6502 diff --git a/SegmentCache.cpp b/SegmentCache.cpp index 934a0be..872bc71 100644 --- a/SegmentCache.cpp +++ b/SegmentCache.cpp @@ -1,18 +1,104 @@ -/* - * File: SegmentCache.cpp - * Author: cmosher - * - * Created on December 10, 2013, 9:56 PM - */ - -#include "SegmentCache.h" -#include -#include -#include - -Segment* SegmentCache::getOrAdd(std::string& id) { - if (this->cache.find(id) == this->cache.end()) { - this->cache[id] = std::make_shared(id); - } - return this->cache[id].get(); -} +/* + * File: SegmentCache.cpp + * Author: cmosher + * + * Created on December 10, 2013, 9:56 PM + */ + +#include "SegmentCache.h" +#include +#include +#include + +Segment* SegmentCache::getOrAdd(const std::string& id) { + if (this->cache.find(id) == this->cache.end()) { + this->cache[id] = std::make_shared(id); + } + return get(id); +} + +Segment* SegmentCache::get(const std::string& id) const { + if (this->cache.find(id) == this->cache.end()) { + throw "Cannot find segment: " + id; + } + return this->cache.at(id).get(); +} + +void SegmentCache::initCommon() { + this->c = new Common( + get("-vss"), get("+vcc"), + get("-clk0"), + get("-irq"), get("-res"), get("-nmi"), + get("+rdy"), get("+so"), + get("-db0"), get("-db1"), get("-db2"), get("-db3"), get("-db4"), get("-db5"), get("-db6"), get("-db7"), + get("-ab0"), get("-ab1"), get("-ab2"), get("-ab3"), get("-ab4"), get("-ab5"), get("-ab6"), get("-ab7"), + get("-ab8"), get("-ab9"), get("-ab10"), get("-ab11"), get("-ab12"), get("-ab13"), get("-ab14"), get("-ab15"), + get("-rw"), get("-sync"), + get("-clk1out"), get("-clk2out"), + get("-a0"), get("-a1"), get("-a2"), get("-a3"), get("-a4"), get("-a5"), get("-a6"), get("-a7"), + get("-x0"), get("-x1"), get("-x2"), get("-x3"), get("-x4"), get("-x5"), get("-x6"), get("-x7"), + get("-y0"), get("-y1"), get("-y2"), get("-y3"), get("-y4"), get("-y5"), get("-y6"), get("-y7"), + get("-pcl0"), get("-pcl1"), get("-pcl2"), get("-pcl3"), get("-pcl4"), get("-pcl5"), get("-pcl6"), get("-pcl7"), + get("-pch0"), get("-pch1"), get("-pch2"), get("-pch3"), get("-pch4"), get("-pch5"), get("-pch6"), get("-pch7"), + get("+Pout0"), get("+Pout1"), get("+Pout2"), get("+Pout3"), get("+Pout4"), /*no P5 */get("+Pout6"), get("+Pout7"), + get("-s0"), get("-s1"), get("-s2"), get("-s3"), get("-s4"), get("-s5"), get("-s6"), get("-s7")); +} + +unsigned char SegmentCache::rData() const { + return Segment::asByte(this->c->DB7, this->c->DB6, this->c->DB5, this->c->DB4, this->c->DB3, this->c->DB2, this->c->DB1, this->c->DB0); +} + +unsigned short SegmentCache::rAddr() const { + return Segment::asWord(this->c->AB15, this->c->AB14, this->c->AB13, this->c->AB12, this->c->AB11, this->c->AB10, this->c->AB9, this->c->AB8, this->c->AB7, this->c->AB6, this->c->AB5, this->c->AB4, this->c->AB3, this->c->AB2, this->c->AB1, this->c->AB0); +} + +unsigned char SegmentCache::rA() const { + return Segment::asByte(this->c->A7, this->c->A6, this->c->A5, this->c->A4, this->c->A3, this->c->A2, this->c->A1, this->c->A0); +} + +unsigned char SegmentCache::rX() const { + return Segment::asByte(this->c->X7, this->c->X6, this->c->X5, this->c->X4, this->c->X3, this->c->X2, this->c->X1, this->c->X0); +} + +unsigned char SegmentCache::rY() const { + return Segment::asByte(this->c->Y7, this->c->Y6, this->c->Y5, this->c->Y4, this->c->Y3, this->c->Y2, this->c->Y1, this->c->Y0); +} + +unsigned char SegmentCache::rS() const { + return Segment::asByte(this->c->S7, this->c->S6, this->c->S5, this->c->S4, this->c->S3, this->c->S2, this->c->S1, this->c->S0); +} + +unsigned short SegmentCache::rPC() const { + return Segment::asWord(this->c->PCH7, this->c->PCH6, this->c->PCH5, this->c->PCH4, this->c->PCH3, this->c->PCH2, this->c->PCH1, this->c->PCH0, this->c->PCL7, this->c->PCL6, this->c->PCL5, this->c->PCL4, this->c->PCL3, this->c->PCL2, this->c->PCL1, this->c->PCL0); +} + +void SegmentCache::setDataSegs(const unsigned char data) { + unsigned char x = data; + + this->c->DB0->set(x & 1); + x >>= 1; + this->c->DB1->set(x & 1); + x >>= 1; + this->c->DB2->set(x & 1); + x >>= 1; + this->c->DB3->set(x & 1); + x >>= 1; + this->c->DB4->set(x & 1); + x >>= 1; + this->c->DB5->set(x & 1); + x >>= 1; + this->c->DB6->set(x & 1); + x >>= 1; + this->c->DB7->set(x & 1); +} + +void SegmentCache::addDataToRecalc(std::set& s) { + s.insert(this->c->DB0); + s.insert(this->c->DB1); + s.insert(this->c->DB2); + s.insert(this->c->DB3); + s.insert(this->c->DB4); + s.insert(this->c->DB5); + s.insert(this->c->DB6); + s.insert(this->c->DB7); +} diff --git a/SegmentCache.h b/SegmentCache.h index 8f49772..e166d4d 100644 --- a/SegmentCache.h +++ b/SegmentCache.h @@ -1,30 +1,185 @@ -/* - * File: SegmentCache.h - * Author: Christopher - * - * Created on December 10, 2013, 9:56 PM - */ - -#ifndef SEGMENTCACHE_H -#define SEGMENTCACHE_H - -#include "trans.h" -#include -#include -#include - -class SegmentCache { -public: - SegmentCache() {} - virtual ~SegmentCache() {} - - Segment* getOrAdd(std::string& id); - -private: - std::map> cache; - - SegmentCache(const SegmentCache&); - SegmentCache& operator=(const SegmentCache&); -}; - -#endif /* SEGMENTCACHE_H */ +/* + * File: SegmentCache.h + * Author: Christopher + * + * Created on December 10, 2013, 9:56 PM + */ + +#ifndef SEGMENTCACHE_H +#define SEGMENTCACHE_H + +#include "trans.h" +#include +#include +#include +#include + +class SegmentCache { +public: + + SegmentCache() { + } + + virtual ~SegmentCache() { + } + + Segment* getOrAdd(const std::string& id); + Segment* get(const std::string& id) const; + + class Common { + public: + Segment* VSS; + Segment* VCC; + Segment* CLK0; + Segment* IRQ; + Segment* RES; + Segment* NMI; + Segment* RDY; + Segment* SO; + Segment* DB0; + Segment* DB1; + Segment* DB2; + Segment* DB3; + Segment* DB4; + Segment* DB5; + Segment* DB6; + Segment* DB7; + Segment* AB0; + Segment* AB1; + Segment* AB2; + Segment* AB3; + Segment* AB4; + Segment* AB5; + Segment* AB6; + Segment* AB7; + Segment* AB8; + Segment* AB9; + Segment* AB10; + Segment* AB11; + Segment* AB12; + Segment* AB13; + Segment* AB14; + Segment* AB15; + Segment* RW; + Segment* SYNC; + Segment* CLK1OUT; + Segment* CLK2OUT; + Segment* A0; + Segment* A1; + Segment* A2; + Segment* A3; + Segment* A4; + Segment* A5; + Segment* A6; + Segment* A7; + Segment* X0; + Segment* X1; + Segment* X2; + Segment* X3; + Segment* X4; + Segment* X5; + Segment* X6; + Segment* X7; + Segment* Y0; + Segment* Y1; + Segment* Y2; + Segment* Y3; + Segment* Y4; + Segment* Y5; + Segment* Y6; + Segment* Y7; + Segment* PCL0; + Segment* PCL1; + Segment* PCL2; + Segment* PCL3; + Segment* PCL4; + Segment* PCL5; + Segment* PCL6; + Segment* PCL7; + Segment* PCH0; + Segment* PCH1; + Segment* PCH2; + Segment* PCH3; + Segment* PCH4; + Segment* PCH5; + Segment* PCH6; + Segment* PCH7; + Segment* P0; + Segment* P1; + Segment* P2; + Segment* P3; + Segment* P4; + Segment* P6; + Segment* P7; + Segment* S0; + Segment* S1; + Segment* S2; + Segment* S3; + Segment* S4; + Segment* S5; + Segment* S6; + Segment* S7; + + Common( + Segment* VSS, Segment* VCC, + Segment* CLK0, + Segment* IRQ, Segment* RES, Segment* NMI, + Segment* RDY, Segment* SO, + Segment* DB0, Segment* DB1, Segment* DB2, Segment* DB3, Segment* DB4, Segment* DB5, Segment* DB6, Segment* DB7, + Segment* AB0, Segment* AB1, Segment* AB2, Segment* AB3, Segment* AB4, Segment* AB5, Segment* AB6, Segment* AB7, + Segment* AB8, Segment* AB9, Segment* AB10, Segment* AB11, Segment* AB12, Segment* AB13, Segment* AB14, Segment* AB15, + Segment* RW, Segment* SYNC, + Segment* CLK1OUT, Segment* CLK2OUT, + Segment* A0, Segment* A1, Segment* A2, Segment* A3, Segment* A4, Segment* A5, Segment* A6, Segment* A7, + Segment* X0, Segment* X1, Segment* X2, Segment* X3, Segment* X4, Segment* X5, Segment* X6, Segment* X7, + Segment* Y0, Segment* Y1, Segment* Y2, Segment* Y3, Segment* Y4, Segment* Y5, Segment* Y6, Segment* Y7, + Segment* PCL0, Segment* PCL1, Segment* PCL2, Segment* PCL3, Segment* PCL4, Segment* PCL5, Segment* PCL6, Segment* PCL7, + Segment* PCH0, Segment* PCH1, Segment* PCH2, Segment* PCH3, Segment* PCH4, Segment* PCH5, Segment* PCH6, Segment* PCH7, + Segment* P0, Segment* P1, Segment* P2, Segment* P3, Segment* P4, /* no P5 */ Segment* P6, Segment* P7, + Segment* S0, Segment* S1, Segment* S2, Segment* S3, Segment* S4, Segment* S5, Segment* S6, Segment* S7) : + VSS(VSS), VCC(VCC), + CLK0(CLK0), + IRQ(IRQ), RES(RES), NMI(NMI), + RDY(RDY), SO(SO), + DB0(DB0), DB1(DB1), DB2(DB2), DB3(DB3), DB4(DB4), DB5(DB5), DB6(DB6), DB7(DB7), + AB0(AB0), AB1(AB1), AB2(AB2), AB3(AB3), AB4(AB4), AB5(AB5), AB6(AB6), AB7(AB7), + AB8(AB8), AB9(AB9), AB10(AB10), AB11(AB11), AB12(AB12), AB13(AB13), AB14(AB14), AB15(AB15), + RW(RW), SYNC(SYNC), + CLK1OUT(CLK1OUT), CLK2OUT(CLK2OUT), + A0(A0), A1(A1), A2(A2), A3(A3), A4(A4), A5(A5), A6(A6), A7(A7), + X0(X0), X1(X1), X2(X2), X3(X3), X4(X4), X5(X5), X6(X6), X7(X7), + Y0(Y0), Y1(Y1), Y2(Y2), Y3(Y3), Y4(Y4), Y5(Y5), Y6(Y6), Y7(Y7), + PCL0(PCL0), PCL1(PCL1), PCL2(PCL2), PCL3(PCL3), PCL4(PCL4), PCL5(PCL5), PCL6(PCL6), PCL7(PCL7), + PCH0(PCH0), PCH1(PCH1), PCH2(PCH2), PCH3(PCH3), PCH4(PCH4), PCH5(PCH5), PCH6(PCH6), PCH7(PCH7), + P0(P0), P1(P1), P2(P2), P3(P3), P4(P4), /* no P5 */ P6(P6), P7(P7), + S0(S0), S1(S1), S2(S2), S3(S3), S4(S4), S5(S5), S6(S6), S7(S7) { + } + ~Common(); + + private: + Common(const Common&); + Common& operator=(const Common&); + }; + + void initCommon(); + Common* c; + + unsigned char rData() const; + unsigned short rAddr() const; + unsigned char rA() const; + unsigned char rX() const; + unsigned char rY() const; + unsigned char rS() const; + unsigned short rPC() const; + + void setDataSegs(const unsigned char data); + void addDataToRecalc(std::set& s); + +private: + std::map > cache; + + SegmentCache(const SegmentCache&); + SegmentCache& operator=(const SegmentCache&); +}; + +#endif /* SEGMENTCACHE_H */ diff --git a/Trace.cpp b/Trace.cpp new file mode 100644 index 0000000..45e73eb --- /dev/null +++ b/Trace.cpp @@ -0,0 +1,79 @@ +/* + * File: Trace.cpp + * Author: cmosher + * + * Created on December 12, 2013, 3:39 PM + */ + +#include "Trace.h" +#include "SegmentCache.h" +#include +#include + +static void pHex(const unsigned char x) { + std::cout << std::setw(2) << std::setfill('0') << std::hex << (unsigned long) x << std::dec; +} + +static void pHexw(const unsigned short x) { + std::cout << std::setw(4) << std::setfill('0') << std::hex << (unsigned long) x << std::dec; +} + +void Trace::dumpSegments() { +// for (int i = 0; i < segs.size(); ++i) { +// seg& s = segs[i]; +// if (s.pullup) { +// std::cout << "U"; +// } else if (s.pulldown) { +// std::cout << "D"; +// } else { +// std::cout << "f"; +// } +// if (s->on) { +// std::cout << "+"; +// } else { +// std::cout << "-"; +// } +// } +// std::cout << std::endl; +} + +void Trace::dumpRegisters() { + std::cout << "A"; + pHex(s.rA()); + std::cout << " X"; + pHex(s.rX()); + std::cout << " Y"; + pHex(s.rY()); + std::cout << " "; + std::cout << (s.c->P7->on ? "N" : "n"); + std::cout << (s.c->P6->on ? "V" : "v"); + std::cout << "."; + std::cout << (s.c->P4->on ? "B" : "b"); + std::cout << (s.c->P3->on ? "D" : "d"); + std::cout << (s.c->P2->on ? "I" : "i"); + std::cout << (s.c->P1->on ? "Z" : "z"); + std::cout << (s.c->P0->on ? "C" : "c"); + std::cout << " S"; + pHex(s.rS()); + std::cout << " PC"; + pHexw(s.rPC()); + if (s.c->CLK1OUT->on) { + std::cout << " PH1 "; + } + if (s.c->CLK2OUT->on) { + std::cout << " PH2"; + if (s.c->RW->on) { + std::cout << " R"; + } else { + std::cout << " W"; + } + } + if (!(s.c->CLK1OUT->on || s.c->CLK2OUT->on)) { + std::cout << " PH- "; + } + std::cout << " DB"; + pHex(s.rData()); + std::cout << " AB"; + pHexw(s.rAddr()); + std::cout << std::endl; +} diff --git a/Trace.h b/Trace.h new file mode 100644 index 0000000..2f3735e --- /dev/null +++ b/Trace.h @@ -0,0 +1,28 @@ +/* + * File: Trace.h + * Author: cmosher + * + * Created on December 12, 2013, 3:39 PM + */ + +#ifndef TRACE_H +#define TRACE_H + +class SegmentCache; + +class Trace { +public: + Trace(const SegmentCache& s) : s(s) {} + virtual ~Trace() {} + + void dumpSegments(); + void dumpRegisters(); + +private: + Trace(const Trace&); + Trace& operator=(const Trace&); + + const SegmentCache& s; +}; + +#endif /* TRACE_H */ diff --git a/TransNetwork.cpp b/TransNetwork.cpp index 298d9a4..b9f3db1 100644 --- a/TransNetwork.cpp +++ b/TransNetwork.cpp @@ -17,6 +17,8 @@ TransNetwork::TransNetwork(std::istream& in) { this->transes.insert(std::make_shared(this->segs.getOrAdd(c1), this->segs.getOrAdd(gate), this->segs.getOrAdd(c2))); in >> c1 >> gate >> c2; } + + this->segs.initCommon(); } TransNetwork::~TransNetwork() { diff --git a/TransNetwork.h b/TransNetwork.h index caad451..838df67 100644 --- a/TransNetwork.h +++ b/TransNetwork.h @@ -13,7 +13,7 @@ #include class TransNetwork { -private: +public: SegmentCache segs; std::set> transes; diff --git a/cpu.cpp b/cpu.cpp index a4d3a38..285fd34 100644 --- a/cpu.cpp +++ b/cpu.cpp @@ -14,6 +14,7 @@ #include "nodes.h" #include "addressbus.h" +#include "SegmentCache.h" @@ -210,8 +211,7 @@ void CPU::step() { */ const bool nextPhase = !segs[n->CLK0].on; - setSeg(n->CLK0, nextPhase); - recalc(n->CLK0); + clock(nextPhase); // database read/write happens during Clock Phase 2 (only) if (segs[n->CLK2OUT].on) { @@ -222,6 +222,11 @@ void CPU::step() { dumpSegs(); } +void CPU::clock(bool phase) { + setSeg(n->CLK0, phase); + recalc(n->CLK0); +} + void CPU::rw() { readBus(); diff --git a/cpu.h b/cpu.h index efedf6c..440ff8c 100644 --- a/cpu.h +++ b/cpu.h @@ -62,13 +62,14 @@ private: unsigned char mRead(unsigned short addr); void mWrite(unsigned short addr, unsigned char data); void rw(); - void step(); void initPins(); public: CPU(AddressBus& addressBus); ~CPU(); + void step(); /* convenience method */ + void clock(bool phase); void powerOn(); void reset(); void tick(); diff --git a/nodes.cpp b/nodes.cpp index 0a46446..66c4176 100644 --- a/nodes.cpp +++ b/nodes.cpp @@ -13,7 +13,7 @@ nodes::nodes(std::map& map_seg_i) { RES = map_seg_i["-res"]; NMI = map_seg_i["-nmi"]; RDY = map_seg_i["+rdy"]; - SO = map_seg_i["+s0"]; + SO = map_seg_i["+so"]; /* data bus (I/O) */ DB0 = map_seg_i["-db0"]; diff --git a/trans.cpp b/trans.cpp index 7b92dd8..56996cb 100644 --- a/trans.cpp +++ b/trans.cpp @@ -6,3 +6,35 @@ */ #include "trans.h" + +unsigned char Segment::asByte(Segment* b7, Segment* b6, Segment* b5, Segment* b4, Segment* b3, Segment* b2, Segment* b1, Segment* b0) { + return + b7->on << 0x7 | + b6->on << 0x6 | + b5->on << 0x5 | + b4->on << 0x4 | + b3->on << 0x3 | + b2->on << 0x2 | + b1->on << 0x1 | + b0->on; +} + +unsigned short Segment::asWord(Segment* bf, Segment* be, Segment* bd, Segment* bc, Segment* bb, Segment* ba, Segment* b9, Segment* b8, Segment* b7, Segment* b6, Segment* b5, Segment* b4, Segment* b3, Segment* b2, Segment* b1, Segment* b0) { + return + bf->on << 0xf | + be->on << 0xe | + bd->on << 0xd | + bc->on << 0xc | + bb->on << 0xb | + ba->on << 0xa | + b9->on << 0x9 | + b8->on << 0x8 | + b7->on << 0x7 | + b6->on << 0x6 | + b5->on << 0x5 | + b4->on << 0x4 | + b3->on << 0x3 | + b2->on << 0x2 | + b1->on << 0x1 | + b0->on; +} diff --git a/trans.h b/trans.h index 0e4dabc..d75739c 100644 --- a/trans.h +++ b/trans.h @@ -23,8 +23,16 @@ public: bool pulldown; bool on; - Segment(std::string& id) : id(id), on(false), pulldown(false), pullup(id[0] == '+') { + Segment(const std::string& id) : id(id), on(false), pulldown(false), pullup(id[0] == '+') { } + + void set(bool up) { + this->pullup = up; + this->pulldown = !up; + } + + static unsigned char asByte(Segment* b7, Segment* b6, Segment* b5, Segment* b4, Segment* b3, Segment* b2, Segment* b1, Segment* b0); + static unsigned short asWord(Segment* b15, Segment* b14, Segment* b13, Segment* b12, Segment* b11, Segment* b10, Segment* b9, Segment* b8, Segment* b7, Segment* b6, Segment* b5, Segment* b4, Segment* b3, Segment* b2, Segment* b1, Segment* b0); }; class Trans { @@ -36,6 +44,7 @@ private: bool on; public: + Trans(Segment* c1, Segment* gate, Segment* c2) : on(false), c1(c1), gate(gate), c2(c2) { c1->c1c2s.insert(this); gate->gates.insert(this); diff --git a/v6502.cpp b/v6502.cpp index 653461f..a163589 100644 --- a/v6502.cpp +++ b/v6502.cpp @@ -37,16 +37,18 @@ // } //} -int xxxmain(int argc, char *argv[]) { +int main(int argc, char *argv[]) { std::ifstream if_trans("transistors"); if (!if_trans.is_open()) { std::cerr << "error opening file: transistors" << std::endl; exit(EXIT_FAILURE); } - TransNetwork n(if_trans); + TransNetwork tn(if_trans); + SegmentCache::Common* n = tn.segs.c; + n->CLK0->on = true; } -int main(int argc, char *argv[]) { +int xxxmain(int argc, char *argv[]) { AddressBus mem; CPU cpu(mem);