diff options
| author | bd <bdunaisky@umass.edu> | 2025-04-02 04:05:18 +0000 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-04-02 04:05:18 +0000 | 
| commit | 9fb95d655393777dde5929182f94de36f903821d (patch) | |
| tree | 4462f35895737460a01fab891a15f87aba2efb70 | |
| parent | 24f0bd8af57381ab3112b5774d4ad23ac80f0718 (diff) | |
| parent | 3eeb345d673bee6d62b04fc8a8a95ab822dc1e45 (diff) | |
Merge pull request #46 from bdunahu/bdunahu
 Ensure all stages only do work if they are not 'OK' 
| -rw-r--r-- | gui/gui.cc | 6 | ||||
| -rw-r--r-- | gui/worker.cc | 139 | ||||
| -rw-r--r-- | inc/ex.h | 2 | ||||
| -rw-r--r-- | inc/id.h | 4 | ||||
| -rw-r--r-- | inc/instr.h | 8 | ||||
| -rw-r--r-- | inc/instrDTO.h | 15 | ||||
| -rw-r--r-- | inc/stage.h | 35 | ||||
| -rw-r--r-- | inc/wb.h | 20 | ||||
| -rw-r--r-- | src/sim/controller.cc | 7 | ||||
| -rw-r--r-- | src/sim/dum.cc | 8 | ||||
| -rw-r--r-- | src/sim/ex.cc | 70 | ||||
| -rw-r--r-- | src/sim/id.cc | 36 | ||||
| -rw-r--r-- | src/sim/if.cc | 5 | ||||
| -rw-r--r-- | src/sim/instrDTO.cc | 7 | ||||
| -rw-r--r-- | src/sim/mm.cc | 44 | ||||
| -rw-r--r-- | src/sim/stage.cc | 59 | ||||
| -rw-r--r-- | src/sim/wb.cc | 82 | ||||
| -rw-r--r-- | tests/controller.cc | 405 | ||||
| -rw-r--r-- | tests/ex.cc | 95 | ||||
| -rw-r--r-- | tests/id.cc | 4 | ||||
| -rw-r--r-- | tests/if.cc | 22 | 
21 files changed, 827 insertions, 246 deletions
| @@ -63,7 +63,7 @@ void displayArrayHTML(QTextEdit *textEdit, const std::array<int, GPR_NUM> &data)      QString tableText = "<table border='1' cellspacing='0' cellpadding='8' style='border-collapse: collapse; width: 100%; border: 2px solid black;'>";      tableText += "<tr>"; -    int index = 1; +    int index = 0;      for (int value : data) {          tableText += QString("<td align='center' style='border: 2px solid black; min-width: 60px; padding: 10px;'>"                               "%1 <sup style='font-size: 10px; font-weight: bold; color: black;'>%2</sup>" @@ -83,7 +83,7 @@ void displayTableHTML(QTextEdit *textEdit, const std::vector<std::array<signed i      textEdit->setReadOnly(false);      QString tableText = "<table border='1' cellspacing='0' cellpadding='8' style='border-collapse: collapse; width: 100%; border: 2px solid black;'>"; -    int index = 1; +    int index = 0;      for (const auto &row : data) {          tableText += "<tr>";          for (signed int value : row) { @@ -118,7 +118,7 @@ void browseAndUploadFile(QTextEdit *textEdit) {      QTextStream in(&file);      QString content; -    int lineNumber = 1; +    int lineNumber = 0;      while (!in.atEnd()) {          QString line = in.readLine(); diff --git a/gui/worker.cc b/gui/worker.cc index ca3ec4b..685b46c 100644 --- a/gui/worker.cc +++ b/gui/worker.cc @@ -2,66 +2,111 @@  Worker::Worker(QObject *parent) : QObject(parent) {} -void Worker::doWork() { -    qDebug() << "Initializing..."; -    this->d = new Dram(0); +void Worker::doWork() +{ +	qDebug() << "Initializing..."; +	this->d = new Dram(0);  	this->c = new Cache(this->d, 0); -    this->if_stage = new IF(nullptr); +	this->if_stage = new IF(nullptr);  	this->id_stage = new ID(if_stage);  	this->ex_stage = new EX(id_stage); -    this->mm_stage = new MM(ex_stage); -    this->wb_stage = new WB(mm_stage); -    this->ct = new Controller(wb_stage, this->c, true); -     -    emit clock_cycles(this->ct->get_clock_cycle(), this->ct->get_pc()); -    emit dram_storage(this->d->view(0,32)); -    emit cache_storage(this->c->view(0,8)); -    emit register_storage(this->ct->get_gprs()); -     -    signed int w; -    w = 0x11223344; -    this->d->write_word(MEM, w, 0x0); -    this->c->write_word(MEM, w, 0x0); -    this->ct->set_gprs(0, w); +	this->mm_stage = new MM(ex_stage); +	this->wb_stage = new WB(mm_stage); +	this->ct = new Controller(wb_stage, this->c, true); + +	emit clock_cycles(this->ct->get_clock_cycle(), this->ct->get_pc()); +	emit dram_storage(this->d->view(0, 32)); +	emit cache_storage(this->c->view(0, 8)); +	emit register_storage(this->ct->get_gprs()); + +	signed int b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, +		b15, b16, b17, b18, b19; +	std::vector<signed int> p; + +	// I-TYPE              /    /    /   / +	b0 = 0b00000010000000000001000000001101; // ADDI $2 $0 0x200; +	b1 = 0b00000000000000010010100000001101; // ADDI $5 $0 0x1; +	b2 = 0b00000000000000000010100010101101; // STORE $5 0($2); +	// I-TYPE              /    /    /   / +	b3 = 0b00000000000000100010100000001101; // ADDI $5 $0 0x2; +	b4 = 0b00000000000000010010100010101101; // STORE $5 1($2); +	// I-TYPE              /    /    /   / +	b5 = 0b00000000000000110010100000001101; // ADDI $5 $0 0x3; +	b6 = 0b00000000000000100010100010101101; // STORE $5 2($2); +	// I-TYPE              /    /    /   / +	b7 = 0b00000000000001000010100000001101; // ADDI $5 $0 0x4; +	b8 = 0b00000000000000110010100010101101; // STORE $5 3($2); +	// // I-TYPE           /    /    /   / +	b9 = 0b00000000000000000010100000001101; // ADDI $5 $0 0x0; +	// //  I-TYPE           /    /    /   / +	b10 = 0b00000000000000110011000000001101; // ADDI $6 $0 0x3; +	// //  J-TYPE                /    /   / +	b11 = 0b00000000000000000011100000001010; // JRL CHECK +	// //  R-TYPE     /    /    /    /    / +	b12 = 0b00000000000100100101000100000100; // ADD $9 $2 $5; +	// //  I-TYPE           /    /    /   / +	b13 = 0b00000000000000000011101001000101; // LOAD $7 0($9); (RAW HAZARD)! +	//  // I-TYPE           /    /    /   / +	b14 = 0b00000000000000010100001001000101; // LOAD $8 1($9); +	//  // R-TYPE     /    /    /    /    / +	b15 = 0b00000000000011101000001110000100; // ADD $7 $7 $8; +	// I-TYPE               /    /    /   / +	b16 = 0b00000000000000000011101001101101; // STORE $7 0($9); +	b17 = 0b00000000000000010010100101001101; // ADDI $5 $5 0x1; +	//  // R-TYPE     /    /    /    /    / +	b18 = 0b00000000000111100101001101000000; // CMP $6 $5 +	//  // J-TYPE                /    /   / +	b19 = 0b11111111111111111100000000010110; // bgt LOOP + +	p = {b0,  b1,  b2,	b3,	 b4,  b5,  b6,	b7,	 b8,  b9, +		 b10, b11, b12, b13, b14, b15, b16, b17, b18, b19}; +	this->d->load(p);  } -Worker::~Worker() { -    emit finished(); -    qDebug() << "Worker destructor called in thread:" << QThread::currentThread(); -    delete this->ct; +Worker::~Worker() +{ +	emit finished(); +	qDebug() << "Worker destructor called in thread:" +			 << QThread::currentThread(); +	delete this->ct;  	delete this->c;  } - -void Worker::refreshDram() { -    qDebug() << "Refreshing Dram"; -    emit dram_storage(this->d->view(0,32)); +void Worker::refreshDram() +{ +	qDebug() << "Refreshing Dram"; +	emit dram_storage(this->d->view(0, 32));  } -void Worker::refreshCache() { -    qDebug() << "Refreshing Dram"; -    emit cache_storage(this->c->view(0,8)); +void Worker::refreshCache() +{ +	qDebug() << "Refreshing Dram"; +	emit cache_storage(this->c->view(0, 8));  } -void Worker::refreshRegisters() { -    qDebug() << "Refreshing Registers"; -    emit register_storage(this->ct->get_gprs()); +void Worker::refreshRegisters() +{ +	qDebug() << "Refreshing Registers"; +	emit register_storage(this->ct->get_gprs());  } -void Worker::runSteps(int steps) { -    qDebug() << "Running for steps: " << steps; -    this->ct->run_for(steps); -    emit dram_storage(this->d->view(0,32)); -    emit cache_storage(this->c->view(0,8)); -    emit register_storage(this->ct->get_gprs()); -    emit clock_cycles(this->ct->get_clock_cycle(), this->ct->get_pc()); +void Worker::runSteps(int steps) +{ +	qDebug() << "Running for steps: " << steps; +	this->ct->run_for(steps); +	emit dram_storage(this->d->view(0, 256)); +	emit cache_storage(this->c->view(0, 8)); +	emit register_storage(this->ct->get_gprs()); +	emit clock_cycles(this->ct->get_clock_cycle(), this->ct->get_pc());  } -void Worker::runStep() { -    qDebug() << "Running for 1 step " ; -    this->ct->advance(OK); -    emit dram_storage(this->d->view(0,32)); -    emit cache_storage(this->c->view(0,8)); -    emit register_storage(this->ct->get_gprs()); -    emit clock_cycles(this->ct->get_clock_cycle(), this->ct->get_pc()); -}
\ No newline at end of file +void Worker::runStep() +{ +	qDebug() << "Running for 1 step "; +	this->ct->advance(WAIT); +	emit dram_storage(this->d->view(0, 256)); +	emit cache_storage(this->c->view(0, 8)); +	emit register_storage(this->ct->get_gprs()); +	qDebug() << "PC " << this->ct->get_pc(); +	emit clock_cycles(this->ct->get_clock_cycle(), this->ct->get_pc()); +} @@ -25,7 +25,7 @@ class EX : public Stage  	 */  	std::unordered_map<  		Mnemonic, -		std::function<void(signed int &s1, signed int s2, signed int s3)>> +		std::function<void(signed int &s1, signed int s2, signed int s3, unsigned int pc)>>  		instr_map;  }; @@ -66,8 +66,8 @@ class ID : public Stage  	 */  	void get_instr_fields(signed int &s1, signed int &s2, signed int &s3, Mnemonic &m, Type &t);  	void decode_R_type(signed int &s1, signed int &s2, signed int &s3); -	void decode_I_type(signed int &s1, signed int &s2, signed int &s3); -	void decode_J_type(signed int &s1, signed int &s2); +	void decode_I_type(signed int &s1, signed int &s2, signed int &s3, Mnemonic &m); +	void decode_J_type(signed int &s1, signed int &s2, signed int &s3);  	/**  	 * Helper for `get_instr_fields`.  	 * Given a raw instruction, returns the mnemonic and type. diff --git a/inc/instr.h b/inc/instr.h index d17613d..2b1807a 100644 --- a/inc/instr.h +++ b/inc/instr.h @@ -1,7 +1,6 @@  #ifndef INSTR_H  #define INSTR_H  #include <functional> -#include <iostream>  #include <unordered_map>  enum Mnemonic { @@ -45,12 +44,7 @@ enum Mnemonic {  	NOP,  }; -enum Type { -	R, -	I, -	J, -	INV -}; +enum Type { R, I, J, INV };  namespace instr  { diff --git a/inc/instrDTO.h b/inc/instrDTO.h index 8249122..b6dec06 100644 --- a/inc/instrDTO.h +++ b/inc/instrDTO.h @@ -47,6 +47,10 @@ class InstrDTO  	 * @return the type of the instruction  	 */  	Type get_type(); +	/** +	 * @return the program counter at the time this instruction was fetched +	 */ +	unsigned int get_pc();  	/**  	 * @param set hist key @@ -72,11 +76,15 @@ class InstrDTO  	 * @param the mnemonic of the instruction  	 */  	void set_mnemonic(Mnemonic); -	 +  	/**  	 * @param the type of the instruction  	 */  	void set_type(Type); +	/** +	 * @param the program counter at the time this instruction was fetched +	 */ +	void set_pc(unsigned int pc);    private:  	/** @@ -100,11 +108,14 @@ class InstrDTO  	 * The mnemonic of the operation.  	 */  	Mnemonic mnemonic; -  	/**  	 * Type of the instruction  	 */  	Type type; +	/** +	 * The PC of the instruction +	 */ +	unsigned int pc;  };  #endif /* INSTRDTO_H_INCLUDED */ diff --git a/inc/stage.h b/inc/stage.h index 03048b0..51ab667 100644 --- a/inc/stage.h +++ b/inc/stage.h @@ -34,7 +34,7 @@ class Stage  	 * ready to accept a new instruction object next cycle.  	 * @return a DTO object containing the next instruction to be processed.  	 * -	 * Must set the status to STALLED when an operation completes. +	 * Must set the status to WAIT when the current instruction is evicted..  	 */  	virtual InstrDTO *advance(Response p); @@ -47,31 +47,33 @@ class Stage  	 * @param the condition code to retrieve,  	 */  	bool get_condition(CC c); -  	/** -	 * Sets the value of the PC register. +	 * Sets the bit in the condition code register corresponding to `c`. +	 * @param the condition code to set. +	 * @param the truthy value to set it to.  	 */ -	void set_pc(unsigned int pc); +	void set_condition(CC c, bool v);  	/**  	 * Squashes the pipeline.  	 */  	void squash(); +	/** +	 * The set of registers currently checked out. +	 */ +	static std::deque<signed int> checked_out; +    protected:  	/**  	 * The function expected to do the majority of the work.  	 * -	 * Must set the status to OK when an operation is ready. +	 * Must set the status to OK when an operation is done. +	 * Must set the status to STALLED when an operation cannot be completed the +	 * current cycle.  	 */  	virtual void advance_helper() = 0;  	/** -	 * Sets the bit in the condition code register corresponding to `c`. -	 * @param the condition code to set. -	 * @param the truthy value to set it to. -	 */ -	void set_condition(CC c, bool v); -	/**  	 * Helper for `check_out`.  	 * Returns true if r are not checked out, false otherwise.  	 * @param a list of register numbers. @@ -79,6 +81,12 @@ class Stage  	 */  	bool is_checked_out(signed int r);  	/** +	 * Stores `d` into the register indexed `v`. +	 * @param the register number. +	 * @param the value to store. +	 */ +	void store_register(signed int v, signed int d); +	/**  	 * Returns the value of the register corresponding to `v`.  	 * @param the register number.  	 * @return the value in the associated register. @@ -112,11 +120,6 @@ class Stage  	 * The current clock cycle.  	 */  	static int clock_cycle; -	// TODO fix this comment after writeback stage -	/** -	 * The set of registers currently checked out. -	 */ -	static std::deque<signed int> checked_out;  	/**  	 * A pointer to the next stage in the pipeline.  	 */ @@ -14,9 +14,27 @@ class WB : public Stage  	 */  	WB(Stage *next);  	using Stage::advance; -	 +    private:  	void advance_helper() override; +	/** +	 * Performs the actual work of storing into a register. +	 */ +	void write_handler(); +	/** +	 * Performs the actual work of processing a jump instruction. +	 */ +	void jump_handler(); +	/** +	 * @return true if the current instruction is an R or I type and is not a +	 * STORE. +	 */ +	bool should_write(); +	/** +	 * @return true if the current instruction is a J type and is not a push. +	 * STORE. +	 */ +	bool should_jump();  };  #endif /* WB_H_INCLUDED */ diff --git a/src/sim/controller.cc b/src/sim/controller.cc index 7e24b3d..65e5676 100644 --- a/src/sim/controller.cc +++ b/src/sim/controller.cc @@ -9,6 +9,7 @@ Controller::Controller(Stage *stage, Storage *storage, bool is_pipelined)  	this->storage = storage;  	this->is_pipelined = is_pipelined;  	this->pc = 0x0; +	this->checked_out = {};  	this->gprs = {0};  	// grant side-door access  	this->id = SIDE; @@ -18,7 +19,7 @@ void Controller::run_for(int number)  {  	int i;  	for (i = 0; i < number; ++i) { -		this->advance(OK); +		this->advance(WAIT);  	}  } @@ -37,9 +38,11 @@ InstrDTO *Controller::advance(Response p)  	InstrDTO *r;  	r = this->next->advance(p);  	++this->clock_cycle; +  	return r;  } -void Controller::advance_helper() { +void Controller::advance_helper() +{  	// TODO: check halt condition and call UI to refresh  } diff --git a/src/sim/dum.cc b/src/sim/dum.cc index dd16660..76d4acd 100644 --- a/src/sim/dum.cc +++ b/src/sim/dum.cc @@ -9,13 +9,12 @@ DUM::DUM(Stage *stage) : Stage(stage) { this->id = IDLE; }  InstrDTO *DUM::advance(Response p)  { -	InstrDTO *r = curr_instr; +	InstrDTO *r = nullptr; -	this->advance_helper(); -	if (this->status == OK && p == OK) { +	if (this->curr_instr && p == WAIT) {  		this->curr_instr->set_time_of(this->id, this->clock_cycle);  		r = new InstrDTO(*this->curr_instr); -		delete curr_instr; +		delete this->curr_instr;  		curr_instr = nullptr;  	} @@ -27,5 +26,4 @@ void DUM::advance_helper() {}  void DUM::set_curr_instr(InstrDTO *d)  {  	this->curr_instr = d; -	this->status = OK;  } diff --git a/src/sim/ex.cc b/src/sim/ex.cc index f22adc0..b6f8a1d 100644 --- a/src/sim/ex.cc +++ b/src/sim/ex.cc @@ -4,11 +4,12 @@  #include "instrDTO.h"  #include "response.h"  #include "stage.h" +#include "utils.h"  #include <unordered_map>  // clang-format off  #define INIT_INSTRUCTION(mnemonic, body)					\ -	{mnemonic, [this](signed int &s1, signed int s2, signed int s3) { \ +	{mnemonic, [this](signed int &s1, signed int s2, signed int s3, unsigned int pc) {	\  		body; \  	}}  // clang-format on @@ -23,6 +24,7 @@ EX::EX(Stage *stage) : Stage(stage)  			ADD,  			{  				s1 = s1 + s2; +				(void)pc;  				(void)s3;  				(void)this;  			}), @@ -31,6 +33,7 @@ EX::EX(Stage *stage) : Stage(stage)  			SUB,  			{  				s1 = s1 - s2; +				(void)pc;  				(void)s3;  				(void)this;  			}), @@ -39,6 +42,7 @@ EX::EX(Stage *stage) : Stage(stage)  			MUL,  			{  				s1 = s1 * s2; +				(void)pc;  				(void)s3;  				(void)this;  			}), @@ -47,6 +51,7 @@ EX::EX(Stage *stage) : Stage(stage)  			QUOT,  			{  				s1 = s1 / s2; +				(void)pc;  				(void)s3;  				(void)this;  			}), @@ -55,6 +60,7 @@ EX::EX(Stage *stage) : Stage(stage)  			REM,  			{  				s1 = s1 % s2; +				(void)pc;  				(void)s3;  				(void)this;  			}), @@ -63,6 +69,7 @@ EX::EX(Stage *stage) : Stage(stage)  			SFTR,  			{  				s1 = s1 >> s2; +				(void)pc;  				(void)s3;  				(void)this;  			}), @@ -71,6 +78,7 @@ EX::EX(Stage *stage) : Stage(stage)  			SFTL,  			{  				s1 = s1 << s2; +				(void)pc;  				(void)s3;  				(void)this;  			}), @@ -79,6 +87,7 @@ EX::EX(Stage *stage) : Stage(stage)  			AND,  			{  				s1 = s1 & s2; +				(void)pc;  				(void)s3;  				(void)this;  			}), @@ -87,6 +96,7 @@ EX::EX(Stage *stage) : Stage(stage)  			OR,  			{  				s1 = s1 | s2; +				(void)pc;  				(void)s3;  				(void)this;  			}), @@ -95,6 +105,7 @@ EX::EX(Stage *stage) : Stage(stage)  			NOT,  			{  				s1 = ~s1; +				(void)pc;  				(void)s3;  				(void)s2;  				(void)this; @@ -104,6 +115,7 @@ EX::EX(Stage *stage) : Stage(stage)  			XOR,  			{  				s1 = s1 ^ s2; +				(void)pc;  				(void)s3;  				(void)this;  			}), @@ -111,6 +123,7 @@ EX::EX(Stage *stage) : Stage(stage)  		INIT_INSTRUCTION(  			ADDV,  			{ +				(void)pc;  				(void)s3;  				(void)s2;  				(void)s1; @@ -120,6 +133,7 @@ EX::EX(Stage *stage) : Stage(stage)  		INIT_INSTRUCTION(  			SUBV,  			{ +				(void)pc;  				(void)s3;  				(void)s2;  				(void)s1; @@ -129,6 +143,7 @@ EX::EX(Stage *stage) : Stage(stage)  		INIT_INSTRUCTION(  			MULV,  			{ +				(void)pc;  				(void)s3;  				(void)s2;  				(void)s1; @@ -138,6 +153,7 @@ EX::EX(Stage *stage) : Stage(stage)  		INIT_INSTRUCTION(  			DIVV,  			{ +				(void)pc;  				(void)s3;  				(void)s2;  				(void)s1; @@ -151,12 +167,14 @@ EX::EX(Stage *stage) : Stage(stage)  						  : this->set_condition(GT, false);  				(s1 == s2) ? this->set_condition(EQ, true)  						   : this->set_condition(EQ, false); +				(void)pc;  				(void)s3;  			}),  		INIT_INSTRUCTION(  			CEV,  			{ +				(void)pc;  				(void)s3;  				(void)s2;  				(void)s1; @@ -168,6 +186,7 @@ EX::EX(Stage *stage) : Stage(stage)  			LOAD,  			{  				s1 = s1 + s3; +				(void)pc;  				(void)s2;  				(void)this;  			}), @@ -175,6 +194,7 @@ EX::EX(Stage *stage) : Stage(stage)  		INIT_INSTRUCTION(  			LOADV,  			{ +				(void)pc;  				(void)s3;  				(void)s2;  				(void)s1; @@ -185,6 +205,7 @@ EX::EX(Stage *stage) : Stage(stage)  			ADDI,  			{  				s1 = s1 + s3; +				(void)pc;  				(void)s2;  				(void)this;  			}), @@ -193,6 +214,7 @@ EX::EX(Stage *stage) : Stage(stage)  			SUBI,  			{  				s1 = s1 - s3; +				(void)pc;  				(void)s2;  				(void)this;  			}), @@ -201,6 +223,7 @@ EX::EX(Stage *stage) : Stage(stage)  			SFTRI,  			{  				s1 = s1 >> s3; +				(void)pc;  				(void)s2;  				(void)this;  			}), @@ -209,6 +232,7 @@ EX::EX(Stage *stage) : Stage(stage)  			SFTLI,  			{  				s1 = s1 << s3; +				(void)pc;  				(void)s2;  				(void)this;  			}), @@ -217,6 +241,7 @@ EX::EX(Stage *stage) : Stage(stage)  			ANDI,  			{  				s1 = s1 & s3; +				(void)pc;  				(void)s2;  				(void)this;  			}), @@ -225,6 +250,7 @@ EX::EX(Stage *stage) : Stage(stage)  			ORI,  			{  				s1 = s1 | s3; +				(void)pc;  				(void)s2;  				(void)this;  			}), @@ -233,6 +259,7 @@ EX::EX(Stage *stage) : Stage(stage)  			XORI,  			{  				s1 = s1 ^ s3; +				(void)pc;  				(void)s2;  				(void)this;  			}), @@ -241,6 +268,7 @@ EX::EX(Stage *stage) : Stage(stage)  			STORE,  			{  				s1 = s1 + s3; +				(void)pc;  				(void)s2;  				(void)this;  			}), @@ -248,6 +276,7 @@ EX::EX(Stage *stage) : Stage(stage)  		INIT_INSTRUCTION(  			STOREV,  			{ +				(void)pc;  				(void)s3;  				(void)s2;  				(void)s1; @@ -259,6 +288,7 @@ EX::EX(Stage *stage) : Stage(stage)  			JMP,  			{  				s1 = s1 + s2; +				(void)pc;  				(void)s3;  				(void)this;  			}), @@ -266,7 +296,7 @@ EX::EX(Stage *stage) : Stage(stage)  		INIT_INSTRUCTION(  			JRL,  			{ -				s1 = this->pc + s2; +				s1 = pc + s2;  				(void)s3;  				(void)this;  			}), @@ -275,6 +305,7 @@ EX::EX(Stage *stage) : Stage(stage)  			JAL,  			{  				s1 = s1 + s2; +				(void)pc;  				(void)s3;  				(void)this;  			}), @@ -282,34 +313,39 @@ EX::EX(Stage *stage) : Stage(stage)  		INIT_INSTRUCTION(  			BEQ,  			{ -				(this->get_condition(EQ)) ? s1 = this->pc + s2 : s1 = this->pc; +				(this->get_condition(EQ)) ? s1 = wrap_address(pc + s2) +										  : s1 = -1;  				(void)s3;  			}),  		INIT_INSTRUCTION(  			BGT,  			{ -				(this->get_condition(GT)) ? s1 = this->pc + s2 : s1 = this->pc; +				(this->get_condition(GT)) ? s1 = wrap_address(pc + s2) +										  : s1 = -1;  				(void)s3;  			}),  		INIT_INSTRUCTION(  			BUF,  			{ -				(this->get_condition(UF)) ? s1 = this->pc + s2 : s1 = this->pc; +				(this->get_condition(UF)) ? s1 = wrap_address(pc + s2) +										  : s1 = -1;  				(void)s3;  			}),  		INIT_INSTRUCTION(  			BOF,  			{ -				(this->get_condition(OF)) ? s1 = this->pc + s2 : s1 = this->pc; +				(this->get_condition(OF)) ? s1 = wrap_address(pc + s2) +										  : s1 = -1;  				(void)s3;  			}),  		INIT_INSTRUCTION(  			PUSH,  			{ +				(void)pc;  				(void)s3;  				(void)s2;  				(void)s1; @@ -319,6 +355,7 @@ EX::EX(Stage *stage) : Stage(stage)  		INIT_INSTRUCTION(  			POP,  			{ +				(void)pc;  				(void)s3;  				(void)s2;  				(void)s1; @@ -329,6 +366,7 @@ EX::EX(Stage *stage) : Stage(stage)  		INIT_INSTRUCTION(  			NOP,  			{ +				(void)pc;  				(void)s3;  				(void)s2;  				(void)s1; @@ -340,19 +378,17 @@ EX::EX(Stage *stage) : Stage(stage)  void EX::advance_helper()  {  	signed int s1, s2, s3; +	unsigned int pc;  	Mnemonic m; -	// it may be good to ensure we are not doing -	// work that has already been done -	if (this->curr_instr) { -		m = this->curr_instr->get_mnemonic(); -		s1 = this->curr_instr->get_s1(); -		s2 = this->curr_instr->get_s2(); -		s3 = this->curr_instr->get_s3(); +	m = this->curr_instr->get_mnemonic(); +	s1 = this->curr_instr->get_s1(); +	s2 = this->curr_instr->get_s2(); +	s3 = this->curr_instr->get_s3(); +	pc = this->curr_instr->get_pc(); -		this->instr_map[m](s1, s2, s3); +	this->instr_map[m](s1, s2, s3, pc ); -		this->curr_instr->set_s1(s1); -		this->status = OK; -	} +	this->curr_instr->set_s1(s1); +	this->status = OK;  } diff --git a/src/sim/id.cc b/src/sim/id.cc index 0b75b64..0c0be91 100644 --- a/src/sim/id.cc +++ b/src/sim/id.cc @@ -48,11 +48,11 @@ void ID::advance_helper()  	Mnemonic m;  	Type t; -	// it may be good to ensure we are not doing -	// work that has already been done -	if (this->curr_instr && this->curr_instr->get_mnemonic() == NONE) { +	if (curr_instr->get_mnemonic() == NOP) +		this->status = OK; +	else {  		s1 = curr_instr->get_instr_bits(); -		get_instr_fields(s1, s2, s3, m ,t); +		get_instr_fields(s1, s2, s3, m, t);  		if (this->status == OK) {  			curr_instr->set_s1(s1);  			curr_instr->set_s2(s2); @@ -63,7 +63,8 @@ void ID::advance_helper()  	}  } -void ID::get_instr_fields(signed int &s1, signed int &s2, signed int &s3, Mnemonic &m, Type &t) +void ID::get_instr_fields( +	signed int &s1, signed int &s2, signed int &s3, Mnemonic &m, Type &t)  {  	unsigned int type;  	this->split_instr(s1, type, m); @@ -75,11 +76,11 @@ void ID::get_instr_fields(signed int &s1, signed int &s2, signed int &s3, Mnemon  		break;  	case 0b01:  		t = I; -		this->decode_I_type(s1, s2, s3); +		this->decode_I_type(s1, s2, s3, m);  		break;  	case 0b10:  		t = J; -		this->decode_J_type(s1, s2); +		this->decode_J_type(s1, s2, s3);  		break;  	case 0b11:  		t = INV; @@ -101,14 +102,17 @@ void ID::decode_R_type(signed int &s1, signed int &s2, signed int &s3)  	r1 = this->read_guard(s1);  	r2 = this->read_guard(s2); -	this->write_guard(s3); -  	this->status = (r1 == OK && r2 == OK) ? OK : STALLED; + +	if (this->status == OK) +		this->write_guard(s3);  } -void ID::decode_I_type(signed int &s1, signed int &s2, signed int &s3) +void ID::decode_I_type( +	signed int &s1, signed int &s2, signed int &s3, Mnemonic &m)  {  	unsigned int s0b, s1b, s2b; +	Response r1;  	s0b = REG_SIZE;  	s1b = s0b + REG_SIZE; @@ -117,16 +121,22 @@ void ID::decode_I_type(signed int &s1, signed int &s2, signed int &s3)  	s2 = GET_MID_BITS(s1, s0b, s1b);  	s1 = GET_LS_BITS(s1, s0b); -	this->status = this->read_guard(s1); -	this->write_guard(s2); +	r1 = this->read_guard(s1); +	if (m != STORE && m != STOREV) { +		this->status = r1; +		if (r1 == OK) +			this->write_guard(s2); +	} else +		this->status = (this->read_guard(s2) == OK && r1 == OK) ? OK : STALLED;  } -void ID::decode_J_type(signed int &s1, signed int &s2) +void ID::decode_J_type(signed int &s1, signed int &s2, signed int &s3)  {  	unsigned int s0b, s1b;  	s0b = REG_SIZE;  	s1b = WORD_SPEC; +	s3 = 0;  	s2 = GET_MID_BITS(s1, s0b, s1b);  	s1 = GET_LS_BITS(s1, s0b); diff --git a/src/sim/if.cc b/src/sim/if.cc index fa8f6c2..85fb27f 100644 --- a/src/sim/if.cc +++ b/src/sim/if.cc @@ -11,14 +11,13 @@ InstrDTO *IF::advance(Response p)  	InstrDTO *r = nullptr;  	this->advance_helper(); -	if (this->curr_instr != nullptr && p == OK) { +	if (this->curr_instr != nullptr && p == WAIT) {  		// mutual consent  		++this->pc;  		this->curr_instr->set_time_of(this->id, this->clock_cycle);  		r = new InstrDTO(*this->curr_instr);  		delete curr_instr;  		curr_instr = nullptr; -		this->status = STALLED;  	}  	return r; @@ -32,9 +31,9 @@ void IF::advance_helper()  	if (this->curr_instr == nullptr) {  		r = this->storage->read_word(this->id, this->pc, bits);  		if (r == OK) { -			this->status = r;  			this->curr_instr = new InstrDTO();  			this->curr_instr->set_instr_bits(bits); +			this->curr_instr->set_pc(this->pc);  		}  	}  } diff --git a/src/sim/instrDTO.cc b/src/sim/instrDTO.cc index b33c26b..aa49b7e 100644 --- a/src/sim/instrDTO.cc +++ b/src/sim/instrDTO.cc @@ -7,8 +7,9 @@ InstrDTO::InstrDTO()  	this->s1 = 0;  	this->s2 = 0;  	this->s3 = 0; -	this->mnemonic = NONE; +	this->mnemonic = ADD;  	this->type = INV; +	this->pc = 0;  }  int InstrDTO::get_time_of(Accessor a) { return this->hist[a]; } @@ -25,6 +26,8 @@ Mnemonic InstrDTO::get_mnemonic() { return this->mnemonic; }  Type InstrDTO::get_type() { return this->type; } +unsigned int InstrDTO::get_pc() { return this->pc; } +  void InstrDTO::set_time_of(Accessor a, int i) { this->hist[a] = i; }  void InstrDTO::set_instr_bits(signed int instr) { this->instr_bits = instr; } @@ -38,3 +41,5 @@ void InstrDTO::set_s3(signed int s) { this->s3 = s; }  void InstrDTO::set_mnemonic(Mnemonic m) { this->mnemonic = m; }  void InstrDTO::set_type(Type t) { this->type = t; } + +void InstrDTO::set_pc(unsigned int pc) { this->pc = pc; } diff --git a/src/sim/mm.cc b/src/sim/mm.cc index cd85056..07a362b 100644 --- a/src/sim/mm.cc +++ b/src/sim/mm.cc @@ -4,26 +4,32 @@  #include "response.h"  #include "stage.h" -MM::MM(Stage *stage) : Stage(stage) { this->id = MEM; }  +MM::MM(Stage *stage) : Stage(stage) { this->id = MEM; } -void MM::advance_helper() { -	Response r; +void MM::advance_helper() +{  	signed int data; -	if(this->curr_instr){ -		if (this->curr_instr->get_mnemonic() == LOAD) { -			r = this->storage->read_word(this->id, this->curr_instr->get_s1(), data); -			if(r == OK){ -				this->status = OK; -				this->curr_instr->set_s2(data); -			} -		} else if (this->curr_instr->get_mnemonic() == STORE) { -			r = this->storage->write_word(this->id, this->curr_instr->get_s2(), this->curr_instr->get_s1()); -			if(r == OK){ -				this->status = OK; -			} -		} else { -			// Mem has no work so just forward the instruction to WB -			this->status = OK; + +	switch (this->curr_instr->get_mnemonic()) { +	case LOAD: +		this->status = this->storage->read_word( +			this->id, this->curr_instr->get_s1(), data); +		if (this->status == OK) { +			this->curr_instr->set_s1(data); +		} else +			this->status = STALLED; +		break; + +	case STORE: +		// TODO signed issues, we aren't wrapping addresses +		this->status = this->storage->write_word( +			this->id, this->curr_instr->get_s2(), this->curr_instr->get_s1()); +		if (this->status != OK) { +			this->status = STALLED;  		} -	}  +		break; + +	default: +		this->status = OK; +	}  } diff --git a/src/sim/stage.cc b/src/sim/stage.cc index be69d77..2857e1f 100644 --- a/src/sim/stage.cc +++ b/src/sim/stage.cc @@ -7,8 +7,7 @@ Stage::Stage(Stage *next)  {  	this->next = next;  	this->curr_instr = nullptr; -	this->status = OK; -	this->checked_out = {}; +	this->status = WAIT;  }  Stage::~Stage() { delete this->next; }; @@ -21,32 +20,36 @@ Storage *Stage::storage;  bool Stage::is_pipelined;  int Stage::clock_cycle; -bool Stage::get_condition(CC c) { -	return (this->gprs[3] >> c) & 1; -} - -void Stage::set_pc(unsigned int pc) { -	this->pc = pc; -} +bool Stage::get_condition(CC c) { return (this->gprs[3] >> c) & 1; }  InstrDTO *Stage::advance(Response p)  {  	InstrDTO *r = nullptr; +	InstrDTO *s = nullptr;  	Response n; -	this->advance_helper(); -	if (this->status == OK && this->curr_instr != nullptr && p == OK) { +	// std::cout << "advance: " << this->id << ": " << this->curr_instr << "?: " << p << ": " << this->checked_out.size() << ": "; +	// if (curr_instr) +	// 	std::cout << curr_instr->get_mnemonic(); +	// for (long unsigned int i = 0; i < this->checked_out.size(); ++i) +	// 	std::cout << this->checked_out[i] << " "; +	// std::cout << std::endl;	 +	if (this->curr_instr && this->status != OK) { +		this->advance_helper(); +	} +	if (this->status == OK && p == WAIT && this->curr_instr) {  		// mutual consent  		this->curr_instr->set_time_of(this->id, this->clock_cycle);  		r = new InstrDTO(*this->curr_instr);  		delete curr_instr;  		curr_instr = nullptr; -		this->status = STALLED; +		this->status = WAIT;  	} -	n = (p != OK || this->status != OK) ? STALLED : OK; -	// the power of consent -	this->curr_instr = this->next->advance(n); +	n = (p != WAIT || this->status != WAIT) ? STALLED : WAIT; +	s = this->next->advance(n); +	if (s) +		this->curr_instr = s;  	return r;  } @@ -73,16 +76,34 @@ signed int Stage::dereference_register(signed int v)  	return r;  } +void Stage::store_register(signed int v, signed int d) +{ +	if (v < 0 || v >= GPR_NUM + V_NUM) { +		throw std::out_of_range(string_format( +			"instruction tried to access register %d, which does " +			"not exist", +			v)); +	} + +	if (v >= GPR_NUM) +		this->vrs[v % GPR_NUM] = d; +	else +		this->gprs[v] = d; +} +  bool Stage::is_checked_out(signed int r)  {  	return std::find(this->checked_out.begin(), this->checked_out.end(), r) !=  		   this->checked_out.end();  } -void Stage::squash(){ -	this->curr_instr->set_mnemonic(NOP); -	this->status = OK; -	if(this->next){ +void Stage::squash() +{ +	if (curr_instr) { +		this->curr_instr->set_mnemonic(NOP); +		this->status = OK; +	} +	if (this->next) {  		this->next->squash();  	}  } diff --git a/src/sim/wb.cc b/src/sim/wb.cc index ac47f25..01768e8 100644 --- a/src/sim/wb.cc +++ b/src/sim/wb.cc @@ -6,34 +6,56 @@  WB::WB(Stage *stage) : Stage(stage) { this->id = WRITE; } -void WB::advance_helper() { -    if(this -> curr_instr) { -        if(this->curr_instr->get_type() == R || this->curr_instr->get_type() == I){  -            if(this->checked_out.size() > 0) { -                signed int reg = this->checked_out.front(); -                this->checked_out.pop_front(); -                if(reg >= GPR_NUM){ -                    // TODO: handle vector instructions -                } else { -                    if(this->curr_instr->get_mnemonic() != STORE && this->curr_instr->get_mnemonic() != STOREV){ -                        this->gprs[reg] = this->curr_instr->get_s1(); -                    } -                } -            } -        } else if (this->curr_instr->get_type() == J) { -            // TODO:handle push pop -            // branch taken -            if(this->pc != this->curr_instr->get_s1()) { -                if(this->curr_instr->get_mnemonic() == JAL){ -                    // set link register to next instruction -                    this->gprs[1] = this->pc + 1; -                } -                this->pc = this->curr_instr->get_s1();   -                //clear pending registers and squash pipeline -                this->checked_out = {}; -                this->next->squash(); -            } -        } -    } -    this->status = OK; +void WB::advance_helper() +{ +	if (this->curr_instr->get_mnemonic() != NOP && +		this->curr_instr->get_type() != INV) { +		if (this->should_write()) +			this->write_handler(); +		else if (this->should_jump()) +			this->jump_handler(); +	} +	this->status = OK; +} + +void WB::write_handler() +{ +	signed int reg; + +	if (this->checked_out.size() < 1) +		throw std::runtime_error("instruction tried to pop a register out of " +								 "an empty queue during writeback."); + +	reg = this->checked_out.front(); +	this->checked_out.pop_front(); +	this->store_register(reg, this->curr_instr->get_s1()); +} + +void WB::jump_handler() +{ +	if (this->curr_instr->get_s1() > 0) { +		if (this->curr_instr->get_mnemonic() == JAL) +			this->gprs[1] = this->pc + 1; +		this->pc = this->curr_instr->get_s1(); +		this->checked_out = {}; +		this->next->squash(); +	} +} + +bool WB::should_jump() +{ +	Type t; + +	t = this->curr_instr->get_type(); +	return t == J; +} + +bool WB::should_write() +{ +	Mnemonic m; +	Type t; + +	m = this->curr_instr->get_mnemonic(); +	t = this->curr_instr->get_type(); +	return (t == R || t == I) && (m != STORE && m != STOREV);  } diff --git a/tests/controller.cc b/tests/controller.cc index de49629..a009a70 100644 --- a/tests/controller.cc +++ b/tests/controller.cc @@ -21,15 +21,27 @@ class ControllerPipeFixture  		IF *f = new IF(nullptr);  		ID *d = new ID(f);  		EX *e = new EX(d); +		MM *m = new MM(e); +		WB *w = new WB(m); +		this->stage_num = 5; -		this->ct = new Controller(e, this->c, true); +		this->ct = new Controller(w, this->c, true);  	}  	~ControllerPipeFixture()  	{  		delete this->ct;  		delete this->c;  	}; - +	void fill_pipe() +	{ +		InstrDTO *i = nullptr; +		int j; +		for (j = 0; j < this->stage_num + 1; ++j) { +			i = this->ct->advance(WAIT); +			REQUIRE(i == nullptr); +		} +	} +	int stage_num;  	Cache *c;  	Dram *d;  	Controller *ct; @@ -51,40 +63,387 @@ TEST_CASE_METHOD(  	CHECK(this->ct->get_pc() == 0);  } -TEST_CASE_METHOD(ControllerPipeFixture, "Add until exec", "[tmp]") +TEST_CASE_METHOD(ControllerPipeFixture, "two num adder", "[full pipe]")  { -	signed int b; +	signed int b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, +		b15;  	std::vector<signed int> p;  	InstrDTO *i; -	b = 0b1010100000000001001101; -	p = {b}; +	// I-TYPE              /    /    /   / +	b0 = 0b00000010000000000001000000001101; // ADDI $2 $0 0x200; +	b1 = 0b00000000000000010010100000001101; // ADDI $5 $0 0x1; +	b2 = 0b00000000000000000010100010101101; // STORE $5 0($2);  (RAW HAZARD w +											 // 1)! +	// I-TYPE              /    /    /   / +	b3 = 0b00000000000000100010100000001101; // ADDI $5 $0 0x2;   (RAW HAZARD)! +	b4 = 0b00000000000000010010100010101101; // STORE $5 1($2);  (RAW HAZARD)! +	// // I-TYPE           /    /    /   / +	b5 = 0b00000000000000000010100000001101; // ADDI $5 $0 0x0; +	// // I-TYPE           /    /    /   / +	b6 = 0b00000000000000010011000000001101; // ADDI $6 $0 0x1; +	// // J-TYPE                /    /   / +	b7 = 0b00000000000000000011100000001010; // JRL CHECK +	// // R-TYPE     /    /    /    /    / +	b8 = 0b00000000000100100101000100000100; // ADD $9 $2 $5; +	// // I-TYPE           /    /    /   / +	b9 = 0b00000000000000000011101001000101; // LOAD $7 0($9); (RAW HAZARD)! +	//  // I-TYPE           /    /    /   / +	b10 = 0b00000000000000010100001001000101; // LOAD $8 1($9); +	//  // R-TYPE     /    /    /    /    / +	b11 = 0b00000000000011101000001110000100; // ADD $7 $7 $8; +	// I-TYPE               /    /    /   / +	b12 = 0b00000000000000000011101001101101; // STORE $7 0($9); +	b13 = 0b00000010000000010010100101001101; // ADDI $5 $5 0x1; +	//  // R-TYPE     /    /    /    /    / +	b14 = 0b00000000000111100101001101000000; // CMP $6 $5 +	//  // J-TYPE                /    /   / +	b15 = 0b11111111111111111100100000010110; // bgt LOOP + +	p = {b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15};  	this->d->load(p); -	// dram -	i = this->ct->advance(OK); +	this->fill_pipe(); +	i = this->ct->advance(WAIT); +	REQUIRE(i != nullptr); + +	CHECK(i->get_time_of(FETCH) == 3); +	CHECK(i->get_time_of(DCDE) == 4); +	CHECK(i->get_time_of(EXEC) == 5); +	CHECK(i->get_time_of(MEM) == 6); +	CHECK(i->get_time_of(WRITE) == 7); +	CHECK(i->get_s1() == 0x200); +	CHECK(i->get_s2() == 0x0); +	CHECK(i->get_s3() == 0x200); +	CHECK(this->ct->get_gprs().at(2) == 0x200); +	CHECK(i->get_mnemonic() == ADDI); +	CHECK(i->get_instr_bits() == b0); +	CHECK(this->ct->checked_out.front() == 0x5); + +	delete i; +	i = this->ct->advance(WAIT); +	REQUIRE(i != nullptr); + +	CHECK(i->get_time_of(FETCH) == 4); +	CHECK(i->get_time_of(DCDE) == 5); +	CHECK(i->get_time_of(EXEC) == 6); +	CHECK(i->get_time_of(MEM) == 7); +	CHECK(i->get_time_of(WRITE) == 8); +	CHECK(i->get_s1() == 0x1); +	CHECK(i->get_s2() == 0x0); +	CHECK(i->get_s3() == 0x1); +	CHECK(this->ct->get_gprs().at(5) == 0x1); +	CHECK(i->get_mnemonic() == ADDI); +	CHECK(i->get_instr_bits() == b1); + +	delete i; +	i = this->ct->advance(WAIT); +	REQUIRE(i == nullptr); +	i = this->ct->advance(WAIT);  	REQUIRE(i == nullptr); -	// fetch -	i = this->ct->advance(OK); +	i = this->ct->advance(WAIT);  	REQUIRE(i == nullptr); -	// decode -	i = this->ct->advance(OK); +	i = this->ct->advance(WAIT);  	REQUIRE(i == nullptr); -	// exec -	i = this->ct->advance(OK); +	i = this->ct->advance(WAIT);  	REQUIRE(i == nullptr); -	// done -	i = this->ct->advance(OK); +	i = this->ct->advance(WAIT); +	REQUIRE(i == nullptr); +	i = this->ct->advance(WAIT);  	REQUIRE(i != nullptr); -	CHECK(i->get_time_of(FETCH) == 3); -	CHECK(i->get_time_of(DCDE) == 4); -	CHECK(i->get_time_of(EXEC) == 5); -	CHECK(i->get_s1() == 42); -	CHECK(i->get_s2() == 0); -	CHECK(i->get_s3() == 42); +	CHECK(i->get_time_of(FETCH) == 5); +	CHECK( +		i->get_time_of(DCDE) == +		8); // the previous conflicting instruction wrote here! +	CHECK(i->get_time_of(EXEC) == 9); +	CHECK(i->get_time_of(MEM) == 14); // waited for fetch + 3 dram +	CHECK(i->get_time_of(WRITE) == 15); +	CHECK(i->get_s1() == 0x200); +	CHECK(i->get_s2() == 0x1); +	CHECK(i->get_s3() == 0x0); +	// NO STORE +	CHECK(this->ct->get_gprs().at(2) == 0x200); +	CHECK(this->ct->get_gprs().at(5) == 0x1); +	CHECK(i->get_mnemonic() == STORE); +	CHECK(i->get_instr_bits() == b2); +	CHECK(this->ct->checked_out.front() == 0x5); + +	delete i; +	i = this->ct->advance(WAIT); +	REQUIRE(i != nullptr); + +	CHECK(i->get_time_of(FETCH) == 8); +	CHECK(i->get_time_of(DCDE) == 9); +	CHECK(i->get_time_of(EXEC) == 14); +	CHECK(i->get_time_of(MEM) == 15); +	CHECK(i->get_time_of(WRITE) == 16); +	CHECK(i->get_s1() == 0x2); +	CHECK(i->get_s2() == 0x1); // the previous value in the destination register +	CHECK(i->get_s3() == 0x2); +	CHECK(this->ct->get_gprs().at(2) == 0x200); +	CHECK(this->ct->get_gprs().at(5) == 0x2);  	CHECK(i->get_mnemonic() == ADDI); -	CHECK(i->get_instr_bits() == b); +	CHECK(i->get_instr_bits() == b3); + +	delete i; +	i = this->ct->advance(WAIT); +	REQUIRE(i == nullptr); +	i = this->ct->advance(WAIT); +	REQUIRE(i == nullptr); +	i = this->ct->advance(WAIT); +	REQUIRE(i != nullptr); + +	CHECK(i->get_time_of(FETCH) == 14); // fetching new line + mem +	CHECK( +		i->get_time_of(DCDE) == +		16); // the previous conflicting instruction wrote here! +	CHECK(i->get_time_of(EXEC) == 17); +	CHECK(i->get_time_of(MEM) == 18); +	CHECK(i->get_time_of(WRITE) == 19); +	CHECK(i->get_s1() == 0x201); +	CHECK(i->get_s2() == 0x2); // address +	CHECK(i->get_s3() == 0x1); // offset +	// NO STORE +	CHECK(this->ct->get_gprs().at(2) == 0x200); +	CHECK(this->ct->get_gprs().at(5) == 0x2); +	CHECK(i->get_mnemonic() == STORE); +	CHECK(i->get_instr_bits() == b4); +	// CHECK(this->ct->checked_out.front() == 0x5); + +	delete i; +	i = this->ct->advance(WAIT); +	REQUIRE(i != nullptr); + +	CHECK(i->get_time_of(FETCH) == 16); +	CHECK(i->get_time_of(DCDE) == 17); +	CHECK(i->get_time_of(EXEC) == 18); +	CHECK(i->get_time_of(MEM) == 19); +	CHECK(i->get_time_of(WRITE) == 20); +	CHECK(i->get_s1() == 0x0); +	CHECK(i->get_s2() == 0x2); +	CHECK(i->get_s3() == 0x0); +	CHECK(this->ct->get_gprs().at(2) == 0x200); +	CHECK(this->ct->get_gprs().at(5) == 0x0); +	CHECK(i->get_mnemonic() == ADDI); +	CHECK(i->get_instr_bits() == b5); + +	delete i; +	i = this->ct->advance(WAIT); +	REQUIRE(i != nullptr); + +	CHECK(i->get_time_of(FETCH) == 17); +	CHECK(i->get_time_of(DCDE) == 18); +	CHECK(i->get_time_of(EXEC) == 19); +	CHECK(i->get_time_of(MEM) == 20); +	CHECK(i->get_time_of(WRITE) == 21); +	CHECK(i->get_s1() == 0x1); +	CHECK(i->get_s2() == 0x0); +	CHECK(i->get_s3() == 0x1); +	CHECK(this->ct->get_gprs().at(2) == 0x200); +	CHECK(this->ct->get_gprs().at(6) == 0x1); +	CHECK(i->get_pc() == 0x6); +	CHECK(this->ct->get_pc() == 0x9); +	CHECK(i->get_mnemonic() == ADDI); +	CHECK(i->get_instr_bits() == b6); + +	delete i; +	i = this->ct->advance(WAIT); +	REQUIRE(i != nullptr); + +	CHECK(i->get_time_of(FETCH) == 18); +	CHECK(i->get_time_of(DCDE) == 19); +	CHECK(i->get_time_of(EXEC) == 20); +	CHECK(i->get_time_of(MEM) == 21); +	CHECK(i->get_time_of(WRITE) == 22); +	CHECK(i->get_s1() == 0xE); +	CHECK(i->get_s2() == 0x7); +	CHECK(this->ct->get_gprs().at(2) == 0x200); +	CHECK(this->ct->get_gprs().at(6) == 0x1); +	CHECK(i->get_pc() == 0x7); +	CHECK(this->ct->get_pc() == 0xE); +	CHECK(i->get_mnemonic() == JRL); +	CHECK(i->get_instr_bits() == b7); + +	delete i; +	i = this->ct->advance(WAIT); +	REQUIRE(i == nullptr); // switching cache lines in fetch +	i = this->ct->advance(WAIT); +	REQUIRE(i == nullptr); +	i = this->ct->advance(WAIT); +	REQUIRE(i != nullptr); + +	CHECK(i->get_mnemonic() == NOP); // squashed + +	delete i; +	i = this->ct->advance(WAIT); // nops? +	REQUIRE(i == nullptr); +	i = this->ct->advance(WAIT); +	REQUIRE(i == nullptr); +	i = this->ct->advance(WAIT); +	REQUIRE(i != nullptr); + +	CHECK( +		i->get_time_of(FETCH) == +		24); // 6 greater than last fetch (4 flush pipe, 2 dram) +	CHECK(i->get_time_of(DCDE) == 25); +	CHECK(i->get_time_of(EXEC) == 26); +	CHECK(i->get_time_of(MEM) == 27); +	CHECK(i->get_time_of(WRITE) == 28); +	CHECK(i->get_s1() == 0x1); +	CHECK(i->get_s2() == 0x0); +	CHECK(i->get_s3() == 0x0); +	CHECK(this->ct->get_gprs().at(2) == 0x200); +	CHECK(this->ct->get_gprs().at(5) == 0x0); +	CHECK(this->ct->get_gprs().at(6) == 0x1); +	CHECK(this->ct->get_condition(GT) == true); +	CHECK(this->ct->get_condition(EQ) == false); +	CHECK(i->get_mnemonic() == CMP); +	CHECK(i->get_instr_bits() == b14); + +	delete i; +	i = this->ct->advance(WAIT); +	REQUIRE(i != nullptr); + +	CHECK(i->get_time_of(FETCH) == 25); +	CHECK(i->get_time_of(DCDE) == 26); +	CHECK(i->get_time_of(EXEC) == 27); +	CHECK(i->get_time_of(MEM) == 28); +	CHECK(i->get_time_of(WRITE) == 29); +	CHECK(i->get_s1() == 0x8); +	CHECK(i->get_s2() == 0b111111111111111111001); +	CHECK(this->ct->get_gprs().at(2) == 0x200); +	CHECK(this->ct->get_gprs().at(5) == 0x0); +	CHECK(this->ct->get_gprs().at(6) == 0x1); +	CHECK(this->ct->get_condition(GT) == true); +	CHECK(this->ct->get_condition(EQ) == false); +	CHECK(this->ct->get_pc() == 0x9); +	CHECK(i->get_mnemonic() == BGT); +	CHECK(i->get_instr_bits() == b15); + +	delete i; +	i = this->ct->advance(WAIT); +	REQUIRE(i == nullptr); +	i = this->ct->advance(WAIT); +	REQUIRE(i == nullptr); +	i = this->ct->advance(WAIT); +	REQUIRE(i != nullptr); + +	CHECK(i->get_mnemonic() == NOP); + +	delete i; +	i = this->ct->advance(WAIT); +	REQUIRE(i != nullptr); // it was already in cache + +	CHECK(i->get_time_of(FETCH) == 29); // clear out pipe (4) +	CHECK(i->get_time_of(DCDE) == 30); +	CHECK(i->get_time_of(EXEC) == 31); +	CHECK(i->get_time_of(MEM) == 32); +	CHECK(i->get_time_of(WRITE) == 33); +	CHECK(i->get_s1() == 0x200); +	CHECK(i->get_s2() == 0x0); +	CHECK(i->get_s3() == 0x0); +	CHECK(this->ct->get_gprs().at(2) == 0x200); +	CHECK(this->ct->get_gprs().at(6) == 0x1); +	CHECK(this->ct->get_gprs().at(9) == 0x200); +	CHECK(i->get_pc() == 0x8); +	CHECK(this->ct->get_pc() == 0xB); +	CHECK(i->get_mnemonic() == ADD); +	CHECK(i->get_instr_bits() == b8); +	CHECK(this->ct->checked_out.front() == 0x7); + +	delete i; +	i = this->ct->advance(WAIT); // RAW +	REQUIRE(i == nullptr); +	i = this->ct->advance(WAIT); +	REQUIRE(i == nullptr); +	i = this->ct->advance(WAIT); +	REQUIRE(i != nullptr); + +	CHECK(i->get_time_of(FETCH) == 30); +	CHECK(i->get_time_of(DCDE) == 33); +	CHECK(i->get_time_of(EXEC) == 34); +	CHECK(i->get_time_of(MEM) == 35); +	CHECK(i->get_time_of(WRITE) == 36); +	CHECK(i->get_s1() == 0x1); +	CHECK(i->get_s2() == 0x0); +	CHECK(i->get_s3() == 0x0); +	CHECK(this->ct->get_gprs().at(2) == 0x200); +	CHECK(this->ct->get_gprs().at(6) == 0x1); +	CHECK(this->ct->get_gprs().at(7) == 0x1); +	CHECK(this->ct->get_gprs().at(9) == 0x200); +	CHECK(i->get_mnemonic() == LOAD); +	CHECK(i->get_instr_bits() == b9); +	CHECK(this->ct->checked_out.front() == 0x8); + +	delete i; +	i = this->ct->advance(WAIT); +	REQUIRE(i != nullptr); + +	CHECK(i->get_time_of(FETCH) == 33); +	CHECK(i->get_time_of(DCDE) == 34); +	CHECK(i->get_time_of(EXEC) == 35); +	CHECK(i->get_time_of(MEM) == 36); +	CHECK(i->get_time_of(WRITE) == 37); +	CHECK(i->get_s1() == 0x2); +	CHECK(i->get_s2() == 0x0); +	CHECK(i->get_s3() == 0x1); +	CHECK(this->ct->get_gprs().at(2) == 0x200); +	CHECK(this->ct->get_gprs().at(6) == 0x1); +	CHECK(this->ct->get_gprs().at(7) == 0x1); +	CHECK(this->ct->get_gprs().at(8) == 0x2); +	CHECK(this->ct->get_gprs().at(9) == 0x200); +	CHECK(i->get_mnemonic() == LOAD); +	CHECK(i->get_instr_bits() == b10); +	CHECK(this->ct->checked_out.front() == 0x7); + +	delete i; +	i = this->ct->advance(WAIT); +	REQUIRE(i == nullptr); +	i = this->ct->advance(WAIT); +	REQUIRE(i == nullptr); +	i = this->ct->advance(WAIT); +	REQUIRE(i != nullptr); + +	CHECK(i->get_time_of(FETCH) == 34); +	CHECK(i->get_time_of(DCDE) == 37); +	CHECK(i->get_time_of(EXEC) == 38); +	CHECK(i->get_time_of(MEM) == 39); +	CHECK(i->get_time_of(WRITE) == 40); +	CHECK(i->get_s1() == 0x3); +	CHECK(i->get_s2() == 0x2); +	CHECK(i->get_s3() == 0x1); +	CHECK(this->ct->get_gprs().at(2) == 0x200); +	CHECK(this->ct->get_gprs().at(6) == 0x1); +	CHECK(this->ct->get_gprs().at(7) == 0x3); +	CHECK(this->ct->get_gprs().at(8) == 0x2); +	CHECK(this->ct->get_gprs().at(9) == 0x200); +	CHECK(i->get_mnemonic() == ADD); +	CHECK(i->get_instr_bits() == b11); + +	delete i; +	i = this->ct->advance(WAIT); +	REQUIRE(i == nullptr); +	i = this->ct->advance(WAIT); +	REQUIRE(i == nullptr); +	i = this->ct->advance(WAIT); +	REQUIRE(i != nullptr); + +	CHECK(i->get_time_of(FETCH) == 37); +	CHECK(i->get_time_of(DCDE) == 40); +	CHECK(i->get_time_of(EXEC) == 41); +	CHECK(i->get_time_of(MEM) == 42); +	CHECK(i->get_time_of(WRITE) == 43); +	CHECK(i->get_s1() == 0x200); +	CHECK(i->get_s2() == 0x3); +	CHECK(i->get_s3() == 0x0); +	CHECK(this->ct->get_gprs().at(2) == 0x200); +	CHECK(this->ct->get_gprs().at(6) == 0x1); +	CHECK(this->ct->get_gprs().at(7) == 0x3); +	CHECK(this->ct->get_gprs().at(8) == 0x2); +	CHECK(this->ct->get_gprs().at(9) == 0x200); +	CHECK(i->get_mnemonic() == STORE); +	CHECK(i->get_instr_bits() == b12);  	delete i;  } diff --git a/tests/ex.cc b/tests/ex.cc index 9543c66..13437f7 100644 --- a/tests/ex.cc +++ b/tests/ex.cc @@ -33,9 +33,9 @@ class EXFixture  		i->set_mnemonic(m);  		this->dum->set_curr_instr(i); -		i = this->ct->advance(OK); +		i = this->ct->advance(WAIT);  		REQUIRE(i == nullptr); -		i = this->ct->advance(OK); +		i = this->ct->advance(WAIT);  		REQUIRE(i != nullptr);  		return i; @@ -640,8 +640,7 @@ TEST_CASE_METHOD(EXFixture, "JRL", "[ex]")  	InstrDTO *i;  	m = JRL; -	s1 = 100, s2 = -42027, s3 = 0; -	this->ct->set_pc(42096); +	s1 = 100, s2 = 69, s3 = 0;  	i = execute_instr(s1, s2, s3, m);  	CHECK(i->get_s1() == 69); @@ -668,6 +667,21 @@ TEST_CASE_METHOD(EXFixture, "JAL", "[ex]")  	delete i;  } +TEST_CASE_METHOD(EXFixture, "BEQ no cond", "[ex]") +{ +	signed int s1, s2, s3; +	Mnemonic m; +	InstrDTO *i; + +	m = BEQ; +	s1 = 100, s2 = 50, s3 = 0; +	i = execute_instr(s1, s2, s3, m); + +	CHECK(i->get_s1() == -1); + +	delete i; +} +  TEST_CASE_METHOD(EXFixture, "BEQ", "[ex]")  {  	signed int s1, s2, s3; @@ -675,13 +689,26 @@ TEST_CASE_METHOD(EXFixture, "BEQ", "[ex]")  	InstrDTO *i;  	m = BEQ; -	s1 = 100, s2 = -42027, s3 = 0; -	this->ct->set_pc(42096); +	s1 = 100, s2 = 50, s3 = 0; +	this->ct->set_condition(EQ, true);  	i = execute_instr(s1, s2, s3, m); -	CHECK(i->get_s1() == 69); -	CHECK(!ct->get_condition(OF)); -	CHECK(!ct->get_condition(UF)); +	CHECK(i->get_s1() == 50); + +	delete i; +} + +TEST_CASE_METHOD(EXFixture, "BGT no cond", "[ex]") +{ +	signed int s1, s2, s3; +	Mnemonic m; +	InstrDTO *i; + +	m = BGT; +	s1 = 100, s2 = 50, s3 = 0; +	i = execute_instr(s1, s2, s3, m); + +	CHECK(i->get_s1() == -1);  	delete i;  } @@ -693,13 +720,26 @@ TEST_CASE_METHOD(EXFixture, "BGT", "[ex]")  	InstrDTO *i;  	m = BGT; +	s1 = 100, s2 = 50, s3 = 0; +	this->ct->set_condition(GT, true); +	i = execute_instr(s1, s2, s3, m); + +	CHECK(i->get_s1() == 50); + +	delete i; +} + +TEST_CASE_METHOD(EXFixture, "BUF no cond", "[ex]") +{ +	signed int s1, s2, s3; +	Mnemonic m; +	InstrDTO *i; + +	m = BUF;  	s1 = 100, s2 = -42027, s3 = 0; -	this->ct->set_pc(42096);  	i = execute_instr(s1, s2, s3, m); -	CHECK(i->get_s1() == 69); -	CHECK(!ct->get_condition(OF)); -	CHECK(!ct->get_condition(UF)); +	CHECK(i->get_s1() == -1);  	delete i;  } @@ -711,13 +751,26 @@ TEST_CASE_METHOD(EXFixture, "BUF", "[ex]")  	InstrDTO *i;  	m = BUF; +	s1 = 100, s2 = 50, s3 = 0; +	this->ct->set_condition(UF, true); +	i = execute_instr(s1, s2, s3, m); + +	CHECK(i->get_s1() == 50); + +	delete i; +} + +TEST_CASE_METHOD(EXFixture, "BOF no cond", "[ex]") +{ +	signed int s1, s2, s3; +	Mnemonic m; +	InstrDTO *i; + +	m = BOF;  	s1 = 100, s2 = -42027, s3 = 0; -	this->ct->set_pc(42096);  	i = execute_instr(s1, s2, s3, m); -	CHECK(i->get_s1() == 69); -	CHECK(!ct->get_condition(OF)); -	CHECK(!ct->get_condition(UF)); +	CHECK(i->get_s1() == -1);  	delete i;  } @@ -729,13 +782,11 @@ TEST_CASE_METHOD(EXFixture, "BOF", "[ex]")  	InstrDTO *i;  	m = BOF; -	s1 = 100, s2 = -42027, s3 = 0; -	this->ct->set_pc(42096); +	s1 = 100, s2 = 50, s3 = 0; +	this->ct->set_condition(OF, true);  	i = execute_instr(s1, s2, s3, m); -	CHECK(i->get_s1() == 69); -	CHECK(!ct->get_condition(OF)); -	CHECK(!ct->get_condition(UF)); +	CHECK(i->get_s1() == 50);  	delete i;  } diff --git a/tests/id.cc b/tests/id.cc index 5270972..77a7cd9 100644 --- a/tests/id.cc +++ b/tests/id.cc @@ -29,9 +29,9 @@ class IDFixture  		i->set_instr_bits(raw);  		this->dum->set_curr_instr(i); -		i = this->ct->advance(OK); +		i = this->ct->advance(WAIT);  		REQUIRE(i == nullptr); -		i = this->ct->advance(OK); +		i = this->ct->advance(WAIT);  		REQUIRE(i != nullptr);  		return i; diff --git a/tests/if.cc b/tests/if.cc index 4ebc47d..d6c1bca 100644 --- a/tests/if.cc +++ b/tests/if.cc @@ -36,7 +36,7 @@ class IFFixture  		int i;  		for (i = 0; i < this->m_delay + 1; ++i) { -			r = this->ct->advance(OK); +			r = this->ct->advance(WAIT);  			// check response  			CHECK(r == nullptr);  		} @@ -52,13 +52,13 @@ class IFFixture  		int i;  		for (i = 0; i < this->c_delay; ++i) { -			r = this->ct->advance(OK); +			r = this->ct->advance(WAIT);  			// check response -			CHECK(r == nullptr); +			REQUIRE(r == nullptr);  		} -		r = this->ct->advance(OK); +		r = this->ct->advance(WAIT);  		// check response -		CHECK(r != nullptr); +		REQUIRE(r != nullptr);  		return r;  	} @@ -103,8 +103,7 @@ TEST_CASE_METHOD(IFFixture, "fetch returns two instuctions", "[if_pipe]")  	delete i;  } -TEST_CASE_METHOD(IFFixture, "fetch waits with old instruction", -"[if_pipe]") +TEST_CASE_METHOD(IFFixture, "fetch waits with old instruction", "[if_pipe]")  {  	InstrDTO *i;  	int j, expected_cycles, fetch_cycles; @@ -115,20 +114,21 @@ TEST_CASE_METHOD(IFFixture, "fetch waits with old instruction",  	for (j = 0; j < this->m_delay + 1; ++j) {  		i = this->ct->advance(STALLED);  		// check response -		CHECK(i == nullptr); +		REQUIRE(i == nullptr);  	}  	for (j = 0; j < this->c_delay; ++j) {  		i = this->ct->advance(STALLED);  		// check response -		CHECK(i == nullptr); +		REQUIRE(i == nullptr);  	}  	for (j = 0; j < expected_cycles - fetch_cycles; ++j) {  		i = this->ct->advance(STALLED);  		// check response -		CHECK(i != nullptr); +		REQUIRE(i != nullptr);  	} -	i = this->ct->advance(OK); +	i = this->ct->advance(WAIT); +	REQUIRE(i != nullptr);  	CHECK(i->get_time_of(FETCH) == expected_cycles);  	REQUIRE(i->get_instr_bits() == this->p[0]); | 
