work
This commit is contained in:
7
.vscode/launch.json
vendored
Normal file
7
.vscode/launch.json
vendored
Normal file
@@ -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": []
|
||||
}
|
||||
1
.vscode/settings.json
vendored
Normal file
1
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{}
|
||||
@@ -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;
|
||||
|
||||
137
UnitTest/Sim/EDORam.hpp
Normal file
137
UnitTest/Sim/EDORam.hpp
Normal file
@@ -0,0 +1,137 @@
|
||||
#include <systemc>
|
||||
#include <vector>
|
||||
|
||||
using namespace sc_core;
|
||||
using namespace sc_dt;
|
||||
|
||||
SC_MODULE(EDORam) {
|
||||
// ports (signals are active-low for strobes; true==inactive, false==asserted)
|
||||
sc_in<bool> RAS; // row strobe (active low)
|
||||
sc_in<bool> UCAS; // upper CAS (active low)
|
||||
sc_in<bool> LCAS; // lower CAS (active low)
|
||||
sc_in<bool> WE; // write enable (we treat WE==true as write for simplicity)
|
||||
sc_in<bool> 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<uint16_t> 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<uint16_t>(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);
|
||||
}
|
||||
};
|
||||
44
UnitTest/Sim/Makefile
Normal file
44
UnitTest/Sim/Makefile
Normal file
@@ -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)
|
||||
10
UnitTest/Sim/TestSimu.cpp
Normal file
10
UnitTest/Sim/TestSimu.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
|
||||
#include <systemc>
|
||||
//#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;
|
||||
}
|
||||
BIN
UnitTest/Sim/bin/sim_test.exe
Normal file
BIN
UnitTest/Sim/bin/sim_test.exe
Normal file
Binary file not shown.
BIN
UnitTest/Sim/bin/test_EDORam.exe
Normal file
BIN
UnitTest/Sim/bin/test_EDORam.exe
Normal file
Binary file not shown.
87
UnitTest/Sim/test_EDORam.cpp
Normal file
87
UnitTest/Sim/test_EDORam.cpp
Normal file
@@ -0,0 +1,87 @@
|
||||
#include <systemc>
|
||||
#include <iostream>
|
||||
#include "EDORam.hpp"
|
||||
|
||||
using namespace sc_core;
|
||||
using namespace sc_dt;
|
||||
|
||||
SC_MODULE(Testbench) {
|
||||
sc_signal<bool> 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;
|
||||
}
|
||||
Reference in New Issue
Block a user