diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..5c7247b --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,7 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..9e26dfe --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/FaultSources.c b/FaultSources.c index 9fe8912..79e4f3d 100644 --- a/FaultSources.c +++ b/FaultSources.c @@ -52,6 +52,7 @@ FaultSource_getNbDeps(const def_eFaultSource eFaultSource) res++; return res; } + void FaultSource_AddScore( def_eFaultSource eFaultSource, double dScore) @@ -62,6 +63,7 @@ FaultSource_AddScore( def_eFaultSource eFaultSource, dScore /= dDivider; ar_dFaultScores[eFaultSource].dScore += dScore; eFaultSource = ar_dFaultScores[eFaultSource].eParrentFaultSource; + dDivider = FaultSource_getNbDeps(eFaultSource); if(dDivider <= 0) dDivider = 1.0; diff --git a/UnitTest/Sim/EDORam.hpp b/UnitTest/Sim/EDORam.hpp new file mode 100644 index 0000000..ccc8f17 --- /dev/null +++ b/UnitTest/Sim/EDORam.hpp @@ -0,0 +1,137 @@ +#include +#include + +using namespace sc_core; +using namespace sc_dt; + +SC_MODULE(EDORam) { + // ports (signals are active-low for strobes; true==inactive, false==asserted) + sc_in RAS; // row strobe (active low) + sc_in UCAS; // upper CAS (active low) + sc_in LCAS; // lower CAS (active low) + sc_in WE; // write enable (we treat WE==true as write for simplicity) + sc_in OE; // output enable (not strictly required) + sc_in< sc_uint<9> > ADDRESS; // address + sc_inout_rv<16> DATA; // bidirectional data bus (resolved) + + SC_CTOR(EDORam) + : addressWidth_(9), dataWidth_(16), memory_(1u << 9, 0) + { + SC_METHOD(process); + sensitive << RAS << UCAS << LCAS << WE << OE << ADDRESS << DATA; + dont_initialize(); + + prevRAS_ = true; + prevUCAS_ = true; + prevLCAS_ = true; + } + +private: + enum State { WAIT_RAS, WAIT_CAS, WAIT_DATA }; + State state_{WAIT_RAS}; + + const unsigned addressWidth_; + const unsigned dataWidth_; + std::vector memory_; + + // previous values for edge detection (active-low strobes) + bool prevRAS_; + bool prevUCAS_; + bool prevLCAS_; + + void process() + { + bool ras = RAS.read(); + bool ucas = UCAS.read(); + bool lcas = LCAS.read(); + bool we = WE.read(); // true => write (chosen convention) + bool oe = OE.read(); + unsigned addr = ADDRESS.read(); + + bool cas_asserted = (ucas == false && lcas == false); // CAS active when both low + bool cas_any_low = (ucas == false || lcas == false); + + switch (state_) { + case WAIT_RAS: + // waiting for RAS falling edge (active low) + if (prevRAS_ == true && ras == false) { + state_ = WAIT_CAS; + } + break; + + case WAIT_CAS: + // row is open, wait for CAS assertion (both low) + if (ras == true) { // RAS rose -> abort/return to idle + releaseDataBus(); + state_ = WAIT_RAS; + } + else if (prevUCAS_ == true && ucas == false && prevLCAS_ == true && lcas == false) { + // CAS both fell -> enter data phase + state_ = WAIT_DATA; + performTransfer(addr, cas_asserted, we, oe); + } + break; + + case WAIT_DATA: + // CAS low: data valid in EDO; continue to drive/sample while CAS low + if (cas_asserted) { + performTransfer(addr, cas_asserted, we, oe); + } + + // CAS rising edge (both high) returns to WAIT_CAS (row still active) + if (prevUCAS_ == false && ucas == true && prevLCAS_ == false && lcas == true) { + releaseDataBus(); + state_ = WAIT_CAS; + } + + // RAS rising -> precharge, go idle + if (ras == true) { + releaseDataBus(); + state_ = WAIT_RAS; + } + break; + } + + prevRAS_ = ras; + prevUCAS_ = ucas; + prevLCAS_ = lcas; + } + + void performTransfer(unsigned addr, bool cas_active, bool we, bool oe) + { + if (!cas_active) return; // only act when CAS is asserted (both low) + + if (we) { + // WRITE: sample the data bus (testbench must drive DATA during write) + sc_lv<16> val = DATA.read(); + // if testbench drives "Z" the conversion yields X; guard against that: + bool has_x = false; + for (unsigned i = 0; i < 16; ++i) { + if (val[i] == sc_dt::SC_LOGIC_X) has_x = true; + } + if (!has_x) { + uint16_t v = static_cast(val.to_uint()); + if (addr < memory_.size()) memory_[addr] = v; + } + } else { + // READ: drive the data bus with stored value (if OE allows) + if (!oe) { + // OE active (we treat OE==false as output enabled) + uint16_t v = (addr < memory_.size()) ? memory_[addr] : 0; + sc_lv<16> lv = sc_lv<16>( (uint64_t)v ); + DATA.write(lv); + } else { + // OE inactive -> leave bus high-Z + releaseDataBus(); + } + } + } + + void releaseDataBus() + { + // drive high-impedance on resolved signal + sc_lv<16> z; + for (unsigned i = 0; i < 16; ++i) z[i] = sc_dt::SC_LOGIC_Z; + DATA.write(z); + } +}; \ No newline at end of file diff --git a/UnitTest/Sim/Makefile b/UnitTest/Sim/Makefile new file mode 100644 index 0000000..6b922d9 --- /dev/null +++ b/UnitTest/Sim/Makefile @@ -0,0 +1,44 @@ +# Sim Unit Test Makefile + +CC := g++ +CFLAGS := -Wall -Wextra -std=gnu++17 -I/usr/local/include -g3 -ggdb +LDFLAGS := -L/usr/local/lib -lm -lsystemc -lstdc++ + +# Directories +SRC_DIR := . +BUILD_DIR := build +BIN_DIR := bin + +# Source and object files +SOURCES := $(wildcard $(SRC_DIR)/*.cpp) +OBJECTS := $(SOURCES:$(SRC_DIR)/%.cpp=$(BUILD_DIR)/%.o) +TARGET := $(BIN_DIR)/sim_test + +# Default target +all: $(TARGET) + +# Create directories +$(BUILD_DIR) $(BIN_DIR): + mkdir -p $@ + +# Link executable +$(TARGET): $(OBJECTS) | $(BIN_DIR) + $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) + +# Compile objects +$(BUILD_DIR)/%.o: $(SRC_DIR)/%.cpp | $(BUILD_DIR) + $(CC) $(CFLAGS) -c -o $@ $< + +# Run tests +run: $(TARGET) + ./$(TARGET) + +# Clean build artifacts +clean: + rm -rf $(BUILD_DIR) $(BIN_DIR) + +# Phony targets +.PHONY: all run clean + +test_EDORam.exe: $(BUILD_DIR)/test_EDORam.o + $(CC) $(CFLAGS) -o $(BIN_DIR)/test_EDORam $^ $(LDFLAGS) \ No newline at end of file diff --git a/UnitTest/Sim/TestSimu.cpp b/UnitTest/Sim/TestSimu.cpp new file mode 100644 index 0000000..a048771 --- /dev/null +++ b/UnitTest/Sim/TestSimu.cpp @@ -0,0 +1,10 @@ + +#include +//#include "EDORam.hpp" + +int main() { + // build modules, bind ports, etc. + sc_core::sc_start(100, sc_core::SC_NS); // run for 100 ns + sc_core::sc_stop(); + return 0; +} \ No newline at end of file diff --git a/UnitTest/Sim/bin/sim_test.exe b/UnitTest/Sim/bin/sim_test.exe new file mode 100644 index 0000000..ebe6cdc Binary files /dev/null and b/UnitTest/Sim/bin/sim_test.exe differ diff --git a/UnitTest/Sim/bin/test_EDORam.exe b/UnitTest/Sim/bin/test_EDORam.exe new file mode 100644 index 0000000..c973250 Binary files /dev/null and b/UnitTest/Sim/bin/test_EDORam.exe differ diff --git a/UnitTest/Sim/test_EDORam.cpp b/UnitTest/Sim/test_EDORam.cpp new file mode 100644 index 0000000..33baffe --- /dev/null +++ b/UnitTest/Sim/test_EDORam.cpp @@ -0,0 +1,87 @@ +#include +#include +#include "EDORam.hpp" + +using namespace sc_core; +using namespace sc_dt; + +SC_MODULE(Testbench) { + sc_signal sigRAS, sigUCAS, sigLCAS, sigWE, sigOE; + sc_signal< sc_uint<9> > sigADDR; + sc_signal_rv<16> sigDATA; // resolved signal for bi-directional bus + + EDORam* ram; + + SC_CTOR(Testbench) { + ram = new EDORam("edoram"); + ram->RAS(sigRAS); + ram->UCAS(sigUCAS); + ram->LCAS(sigLCAS); + ram->WE(sigWE); + ram->OE(sigOE); + ram->ADDRESS(sigADDR); + ram->DATA(sigDATA); + + SC_THREAD(run); + } + + void run() { + // init: all strobes inactive (true) + sigRAS = true; sigUCAS = true; sigLCAS = true; + sigWE = false; // choose WE=false as read, WE=true as write + sigOE = true; // OE true => output disabled; OE false => output enabled + sigADDR = 0; + sigDATA.write("ZZZZZZZZZZZZZZZZ"); // high-Z + + wait(10, SC_NS); + + // WRITE cycle: write 0x1234 at addr 1 + unsigned addr = 1; + uint16_t write_val = 0x1234; + sigADDR = addr; + // testbench drives data during write + sc_lv<16> drive_val = sc_lv<16>( (uint64_t)write_val ); + sigDATA.write(drive_val); + + sigWE = true; // indicate write + // RAS falling + sigRAS = false; + wait(5, SC_NS); + // CAS falling (both) + sigUCAS = false; sigLCAS = false; + wait(5, SC_NS); + // CAS rising + sigUCAS = true; sigLCAS = true; + wait(5, SC_NS); + // RAS rising -> end + sigRAS = true; + // release testbench drive + sigDATA.write("ZZZZZZZZZZZZZZZZ"); + sigWE = false; + wait(10, SC_NS); + + // READ cycle: read addr 1 + sigADDR = addr; + sigOE = false; // enable outputs from RAM when reading + // RAS falling + sigRAS = false; + wait(5, SC_NS); + // CAS falling + sigUCAS = false; sigLCAS = false; + wait(5, SC_NS); + // sample data bus (RAM should drive) + sc_lv<16> read_lv = sigDATA.read(); + uint16_t read_val = (uint16_t)read_lv.to_uint64(); + std::cout << "READ val = 0x" << std::hex << read_val << " expected 0x" << write_val << std::dec << std::endl; + + // finish + sc_stop(); + } +}; + +int sc_main(int argc, char* argv[]) +{ + Testbench tb("tb"); + sc_start(); + return 0; +} \ No newline at end of file