diff options
| author | Clément Zrounba <6691770+clement-z@users.noreply.github.com> | 2023-09-30 23:06:01 +0200 |
|---|---|---|
| committer | Clément Zrounba <6691770+clement-z@users.noreply.github.com> | 2023-09-30 23:26:46 +0200 |
| commit | ff9b8bb838ecdfbfc1dc81038fcf3b2a87636982 (patch) | |
| tree | 21f27be782ce11c6d00b96ce100a2bff88141b2e /src/tb | |
| download | specs-ff9b8bb838ecdfbfc1dc81038fcf3b2a87636982.tar.gz specs-ff9b8bb838ecdfbfc1dc81038fcf3b2a87636982.zip | |
Initial release
Diffstat (limited to 'src/tb')
| -rw-r--r-- | src/tb/alltestbenches.cpp | 28 | ||||
| -rw-r--r-- | src/tb/alltestbenches.h | 22 | ||||
| -rw-r--r-- | src/tb/crow_tb.cpp | 216 | ||||
| -rw-r--r-- | src/tb/crow_tb.h | 30 | ||||
| -rw-r--r-- | src/tb/detector_tb.cpp | 127 | ||||
| -rw-r--r-- | src/tb/detector_tb.h | 30 | ||||
| -rw-r--r-- | src/tb/directional_coupler_tb.cpp | 150 | ||||
| -rw-r--r-- | src/tb/directional_coupler_tb.h | 31 | ||||
| -rw-r--r-- | src/tb/freqsweep_tb.cpp | 213 | ||||
| -rw-r--r-- | src/tb/freqsweep_tb.h | 33 | ||||
| -rw-r--r-- | src/tb/lambda_tb.cpp | 102 | ||||
| -rw-r--r-- | src/tb/lambda_tb.h | 31 | ||||
| -rw-r--r-- | src/tb/merger_tb.cpp | 126 | ||||
| -rw-r--r-- | src/tb/merger_tb.h | 30 | ||||
| -rw-r--r-- | src/tb/mesh_tb.cpp | 130 | ||||
| -rw-r--r-- | src/tb/mesh_tb.h | 29 | ||||
| -rw-r--r-- | src/tb/mzi_tb.cpp | 86 | ||||
| -rw-r--r-- | src/tb/mzi_tb.h | 31 | ||||
| -rw-r--r-- | src/tb/pcm_device_tb.cpp | 129 | ||||
| -rw-r--r-- | src/tb/pcm_device_tb.h | 29 | ||||
| -rw-r--r-- | src/tb/phase_shifter_tb.cpp | 129 | ||||
| -rw-r--r-- | src/tb/phase_shifter_tb.h | 32 | ||||
| -rw-r--r-- | src/tb/ring_tb.cpp | 85 | ||||
| -rw-r--r-- | src/tb/ring_tb.h | 29 | ||||
| -rw-r--r-- | src/tb/splitter_tb.cpp | 123 | ||||
| -rw-r--r-- | src/tb/splitter_tb.h | 29 | ||||
| -rw-r--r-- | src/tb/wg_tb.cpp | 143 | ||||
| -rw-r--r-- | src/tb/wg_tb.h | 28 |
28 files changed, 2201 insertions, 0 deletions
diff --git a/src/tb/alltestbenches.cpp b/src/tb/alltestbenches.cpp new file mode 100644 index 0000000..107dfdc --- /dev/null +++ b/src/tb/alltestbenches.cpp @@ -0,0 +1,28 @@ +#include <map> +#include <tb/alltestbenches.h> + +#if defined(BUILD_TB) && BUILD_TB == 1 +std::map<std::string, tb_func_t> tb_map = { + { "wg", wg_tb_run }, + { "waveguide", wg_tb_run }, + { "merg", Merger_tb_run }, + { "merger", Merger_tb_run }, + { "dc", DirectionalCoupler_tb_run }, + { "directional_coupler", DirectionalCoupler_tb_run }, + { "spli", Splitter_tb_run }, + { "splitter", Splitter_tb_run }, + { "det", Detector_tb_run }, + { "detector", Detector_tb_run }, + { "pcm", PCMElement_tb_run }, + { "mzi", MZI_tb_run }, + { "ring", Ring_tb_run }, + { "ac_add_drop", freqsweep_tb_run_add_drop }, + { "ac_crow", crow_tb_run }, + { "lambda", lambda_tb_run }, + { "phaseshifter", ps_tb_run }, + { "ps", ps_tb_run }, + { "mesh", mesh_tb_run }, +}; +#else +std::map<std::string, tb_func_t> tb_map = {}; +#endif diff --git a/src/tb/alltestbenches.h b/src/tb/alltestbenches.h new file mode 100644 index 0000000..49043bb --- /dev/null +++ b/src/tb/alltestbenches.h @@ -0,0 +1,22 @@ +#pragma once + +#include <tb/detector_tb.h> +#include <tb/directional_coupler_tb.h> +#include <tb/merger_tb.h> +#include <tb/pcm_device_tb.h> +#include <tb/splitter_tb.h> +#include <tb/wg_tb.h> +#include "tb/mzi_tb.h" +#include "tb/ring_tb.h" +#include "tb/freqsweep_tb.h" +#include "tb/crow_tb.h" +#include "tb/lambda_tb.h" +#include "tb/phase_shifter_tb.h" +#include "mesh_tb.h" + +#include <map> +#include <string> + +typedef void (*tb_func_t)(); + +extern std::map<std::string, tb_func_t> tb_map; diff --git a/src/tb/crow_tb.cpp b/src/tb/crow_tb.cpp new file mode 100644 index 0000000..91a816c --- /dev/null +++ b/src/tb/crow_tb.cpp @@ -0,0 +1,216 @@ +#include <ctime> +#include <iomanip> +#include <tb/crow_tb.h> + +#include <cstdlib> +#include <unistd.h> +#include <chrono> + +#include <waveguide.h> +#include <directional_coupler.h> +#include <probe.h> +#include <crow.h> +#include <specs.h> +#include "time_monitor.h" + +#include "general_utils.h" + +using namespace std; +using namespace std::chrono; + + +/* ----------------------------------------------------------------------------- * + This testbench is called freqsweep because it is capable of this + type of simulation, but it is also possible to set it as a time-domain + simulation depending on the mode chosen when calling SPECS. Example: + + specs -t ac_add_drop -m fd -> will perform the frequency sweep + specs -t ac_add_drop -m td -> will perform the time domain simulation + +/ ----------------------------------------------------------------------------- */ + +// ---------------- Use this variable to change the size of the CROW ----------- + size_t nrings_crow = 3; +// ----------------------------------------------------------------------------- + +void crow_tb::run_td() +{ + bool verbose = true; + if (specsGlobalConfig.simulation_mode == OpticalOutputPortMode::TIME_DOMAIN) + { + int npulses = 4; + double lambda = 1554.3719e-9; + lambda = 1.561931948453715e-6; + lambda = 1538.3277504e-9; + lambda = 1543e-9; + lambda = 1556.5742279e-9; + lambda = 1556.32782563158025368466e-9; + lambda = 1556e-9; + lambda = 1553e-9; + //lambda = 1550e-9; + double tpulse = 1e-9; + double deadtime = tpulse; + + + // Wait one tick that all sc_threads are started and on their first `wait` call + wait(SC_ZERO_TIME); + + if (verbose) + { + cout << "----------------------------" <<endl; + cout << "Starting time-domain simulation" << endl; + } + for (int i = 0; i < npulses; ++i) + { + IN->write(OpticalSignal(1, lambda)); + wait(tpulse, SC_SEC); + // //ADD.write(OpticalSignal(polar<double>(1, M_PI_2), lambda)); + // //ADD.write(OpticalSignal(polar<double>(0,0), lambda)); + IN->write(OpticalSignal(0, lambda)); + // ADD.write(OpticalSignal(0, lambda)); + wait(deadtime, SC_SEC); + } + } + + while (true) { wait(); } +} + +void crow_tb::run_fd() +{ + bool verbose = true; + if (specsGlobalConfig.simulation_mode == OpticalOutputPortMode::FREQUENCY_DOMAIN) + { + auto lambda_center = 1550e-9; + auto lambda_span = 2e-9; + auto dlambda = 0.001e-9; + auto lambda_min = lambda_center - lambda_span/2; + auto lambda_max = lambda_center + lambda_span/2; + // lambda_min = 1545e-9; + // lambda_max = 1569e-9; + lambda_min = 299792458.0/195e12; + lambda_max = 299792458.0/190e12; + lambda_min = 1556e-9; + lambda_span = lambda_max - lambda_min; + dlambda = lambda_span / 10000; + + // Wait one tick that all sc_threads are started and on their first `wait` call + wait(SC_ZERO_TIME); + //wait(lambda_min, SC_SEC); + + auto tic = high_resolution_clock::now(); + auto toc = high_resolution_clock::now(); + + if (verbose) + { + cout << "----------------------------" <<endl; + cout << "Starting sweep" << endl; + } + int i = 0; + int n = ceil(lambda_span / dlambda); + for (auto lambda = lambda_min; lambda < lambda_max + dlambda; lambda += dlambda) + { + ++i; + if (true || (verbose && i % (int)(n/20) == 0)) + { + toc = high_resolution_clock::now(); + auto duration = duration_cast<microseconds>(toc - tic); + tic = toc; + cout << duration.count()/1000.0 << "ms" << endl; + cout << endl; + cout << fixed << setprecision(1) << (lambda-lambda_min)/lambda_span * 100.0 << "%" << endl; + cout << setprecision(20) << lambda * 1e9 << "nm" << endl; + } + IN->write(OpticalSignal(sqrt(1), lambda)); + ADD->write(OpticalSignal(0, lambda)); + //ADD.write(OpticalSignal(polar<double>(0, 0), lambda)); + //ADD.write(OpticalSignal(polar<double>(sqrt(0.5), -M_PI_2), lambda)); + wait(dlambda, SC_SEC); + } + if (verbose) + { + cout << "----------------------------" <<endl; + cout << "Sweep over (" << n << " points)" << endl; + } + } + while (true) { wait(); } +} + +void crow_tb::monitor() +{ + unsigned long long event_counter = 0; + while(true) + { + wait(); + continue; + event_counter++; + std::cout << sc_time_stamp() << ":" << std::endl + << "\tIN: " << IN->read() << std::endl + << "\tADD: " << ADD->read() << std::endl + << "\tTHROUGH: " << THROUGH->read() << std::endl + << "\tDROP: " << DROP->read() << std::endl + << "\tCOUNT: " << event_counter << std::endl; + } + +} + +void crow_tb_run() +{ + specsGlobalConfig.applyEngineResolution(); + + spx::oa_signal_type IN("IN"), THROUGH("THROUGH"), DROP("DROP"), ADD("ADD"); + + crow_tb tb1("tb1"); + tb1.IN(IN); + tb1.ADD(ADD); + tb1.THROUGH(THROUGH); + tb1.DROP(DROP); + + // pid_t pid = fork(); + CROW *pc; + // if(pid) + pc = new CROW("crow", nrings_crow); + // else + // pc = new Crow("crow", 5); + pc->p_in(IN); + pc->p_add(ADD); + pc->p_out_t(THROUGH); + pc->p_out_d(DROP); + + pc->setRingLength(2*30e-6); + pc->m_loss_db_cm = 2.0; + pc->m_coupling_through = 1 - pow(0.83645, 2.0); + // pc->m_coupling_through = 0.5; + pc->m_neff = 2.6391; + pc->m_ng = 4.3416; + + pc->m_ring_length = 500.0*1.55e-6 + 1.55e-6/2.0; + pc->m_loss_db_cm = 2.0; + pc->m_coupling_through = 1 - 0.2; + pc->m_neff = 1; + pc->m_ng = 2; + + pc->init(); //instantiating all nets + + Probe pthrough("pthrough", true, true, false, true); + pthrough.p_in(THROUGH); + // + Probe pcross("pcross", true, true, false, false); + pcross.p_in(DROP); + + specsGlobalConfig.trace_filename = "traces/crow_tb"; + + // Apply SPECS options specific to the testbench + // specsGlobalConfig.simulation_mode = OpticalOutputPortMode::EVENT_DRIVEN; + specsGlobalConfig.trace_all_optical_nets = 0; + + // Run SPECS pre-simulation code + specsGlobalConfig.prepareSimulation(); + + // Start simulation + sc_start(50e-9, SC_SEC); + + std::cout << std::endl << std::endl; + std::cout << ".vcd trace file: " << specsGlobalConfig.trace_filename << std::endl; + + sc_close_vcd_trace_file(specsGlobalConfig.default_trace_file); +} diff --git a/src/tb/crow_tb.h b/src/tb/crow_tb.h new file mode 100644 index 0000000..473708d --- /dev/null +++ b/src/tb/crow_tb.h @@ -0,0 +1,30 @@ +#pragma once + +#include <optical_signal.h> +#include <specs.h> +#include <systemc.h> + +class crow_tb : public sc_module { +public: + spx::oa_port_out_type IN; + spx::oa_port_out_type ADD; + spx::oa_port_in_type THROUGH; + spx::oa_port_in_type DROP; + + void run_fd(); + void run_td(); + void monitor(); + + SC_CTOR(crow_tb) + { + SC_THREAD(run_fd); + SC_THREAD(run_td); + SC_THREAD(monitor); + if (false) + sensitive << IN << ADD << THROUGH << DROP; + } +}; + +void crow_tb_run(); + +extern size_t nrings_crow; diff --git a/src/tb/detector_tb.cpp b/src/tb/detector_tb.cpp new file mode 100644 index 0000000..e296d26 --- /dev/null +++ b/src/tb/detector_tb.cpp @@ -0,0 +1,127 @@ +#include <ctime> +#include <iomanip> +#include <tb/detector_tb.h> + +#include "general_utils.h" + +void Detector_tb::run_1() +{ + IN->write(OpticalSignal(sqrt(1.0), 1550e-9)); + wait(100, SC_MS); + IN->write(OpticalSignal(0, 1550e-9)); + wait(100, SC_MS); + IN->write(OpticalSignal(sqrt(1.0), 1551e-9)); + + + + while (true) { wait(); } +} + +void Detector_tb::monitor() +{ + unsigned int event_counter = 0; + unsigned int success_counter = 0; + const unsigned int test_number = 3; + while(true) + { + wait(); + event_counter++; + std::cout << sc_time_stamp() << ":" << std::endl + << "\tIN: " << IN->read() << std::endl + << "\tREADOUT: " << READOUT.read() << std::endl + << "\tREADOUT2: " << READOUT2.read() << std::endl + << "\tCOUNT: " << event_counter << std::endl; + + if(event_counter == 2) + { + if ((is_close(READOUT.read(), 1, 1e-3)) && (is_close(READOUT2.read(), 1, 1e-3))) + success_counter++; + else + { + std::cout << "-----------------/! \\---------------" << std::endl; + std::cout << "Failure!" << std::endl; + std::cout << "Expected 1A as both output currents!" << std::endl; + std::cout << "-----------------/! \\---------------" << std::endl; + } + } + if(event_counter == 4) + { + if ((is_close(READOUT.read(), 0, 1e-4)) && (is_close(READOUT2.read(), 0, 1e-4))) + success_counter++; + else + { + std::cout << "-----------------/! \\---------------" << std::endl; + std::cout << "Failure!" << std::endl; + std::cout << "Expected 0A as output currents!" << std::endl; + std::cout << "-----------------/! \\---------------" << std::endl; + } + } + if(event_counter == 6) + { + if (!is_close(READOUT.read(), READOUT2.read(), 1e-7)) + success_counter++; + else + { + std::cout << "-----------------/! \\---------------" << std::endl; + std::cout << "Failure!" << std::endl; + std::cout << "Expected slightly different currents (different noise seed)!" << std::endl; + std::cout << "Is the noise ON?" << std::endl; + std::cout << "-----------------/! \\---------------" << std::endl; + } + + std::cout << "-----------------/! \\---------------" << std::endl; + std::cout << "Test finished!" << std::endl; + std::cout << "Success rate: " << success_counter << "/" << test_number << std::endl; + std::cout << "-----------------/! \\---------------" << std::endl; + } + + } +} + +void Detector_tb_run() +{ + // Apply SPECS resolution before creating any device + specsGlobalConfig.applyEngineResolution(); + + spx::oa_signal_type IN; + sc_signal<double> READOUT, READOUT2; + + Detector uut("uut", 1, 100e-12, false); + uut.p_in(IN); + uut.p_readout(READOUT); + + Detector uut2("uut2", 1, 100e-12, false); + uut2.p_in(IN); + uut2.p_readout(READOUT2); + + Detector_tb tb("tb"); + tb.IN(IN); + tb.READOUT(READOUT); + tb.READOUT2(READOUT2); + + // Open Trace file + std::string trace_filename = "traces/"; + trace_filename += "detector_tb"; + specsGlobalConfig.trace_filename = trace_filename; + + // Apply SPECS options specific to the testbench + specsGlobalConfig.simulation_mode = OpticalOutputPortMode::EVENT_DRIVEN; + specsGlobalConfig.trace_all_optical_nets = 0; + + Probe probe_detector("probe_detector",specsGlobalConfig.default_trace_file); + probe_detector.p_in(IN); + + // Run SPECS pre-simulation code + specsGlobalConfig.prepareSimulation(); + + // custom traces should come after prepareSimulation !! + sc_trace(specsGlobalConfig.default_trace_file, READOUT, "READOUT"); + + // Start simulation + sc_start(); + + std::cout << std::endl << std::endl; + std::cout << ".vcd trace file: " << specsGlobalConfig.trace_filename << std::endl; + + sc_close_vcd_trace_file(specsGlobalConfig.default_trace_file); +} diff --git a/src/tb/detector_tb.h b/src/tb/detector_tb.h new file mode 100644 index 0000000..39b05dc --- /dev/null +++ b/src/tb/detector_tb.h @@ -0,0 +1,30 @@ +#pragma once + +#include <detector.h> +#include <optical_signal.h> +#include <systemc.h> +#include <probe.h> +#include <specs.h> +#include <waveguide.h> + +SC_MODULE(Detector_tb) +{ +public: + spx::oa_port_out_type IN; + sc_in<double> READOUT, READOUT2; + + void run_1(); + void monitor(); + SC_CTOR(Detector_tb) + { + SC_HAS_PROCESS(Detector_tb); + + SC_THREAD(run_1); + + SC_THREAD(monitor); + sensitive << IN << READOUT << READOUT2; + } +}; + +void Detector_tb_run(); + diff --git a/src/tb/directional_coupler_tb.cpp b/src/tb/directional_coupler_tb.cpp new file mode 100644 index 0000000..1954414 --- /dev/null +++ b/src/tb/directional_coupler_tb.cpp @@ -0,0 +1,150 @@ +#include <ctime> +#include <iomanip> +#include <tb/directional_coupler_tb.h> + +#include "general_utils.h" +#include "generic_2x2_coupler.h" + +void DirectionalCoupler_tb::run_1() +{ + IN1->write(OpticalSignal(1.0, 1550e-9)); + wait(100, SC_MS); + IN2->write(OpticalSignal(1.0, 1550e-9)); + wait(100, SC_MS); + + while (true) { wait(); } +} + +void DirectionalCoupler_tb::monitor() +{ + unsigned int event_counter = 0; + unsigned int success_counter = 0; + const unsigned int test_number = 3; + + while(true) + { + wait(); + event_counter++; + std::cout << sc_time_stamp() << ":" << std::endl + << "\tIN1: " << IN1->read() << std::endl + << "\tIN2: " << IN2->read() << std::endl + << "\tOUT1: " << OUT1->read() << std::endl + << "\tOUT2: " << OUT2->read() << std::endl + << "\tCOUNT: " << event_counter << std::endl; + + if(event_counter == 2) + { + if (is_close(norm(OUT1->read().m_field), 0.05, 1e-4) && is_close(norm(OUT2->read().m_field), 0.45, 1e-4)) + success_counter++; + else + { + std::cout << "-----------------/! \\---------------" << std::endl; + std::cout << "Failure!" << std::endl; + std::cout << "Expected 0.05W/0.45 as output power!" << std::endl; + std::cout << "-----------------/! \\---------------" << std::endl; + } + if (is_close(arg(OUT2->read().m_field), 1.5708, 1e-4)) + success_counter++; + else + { + std::cout << "-----------------/! \\---------------" << std::endl; + std::cout << "Failure!" << std::endl; + std::cout << "Expected pi/2 as phase in OUT2!" << std::endl; + std::cout << "-----------------/! \\---------------" << std::endl; + } + } + if(event_counter == 4) + { + if (is_close(arg(OUT1->read().m_field), 1.2490, 1e-4)) + success_counter++; + else + { + std::cout << "-----------------/! \\---------------" << std::endl; + std::cout << "Failure!" << std::endl; + std::cout << "Expected 1.2490 as phase in OUT1!" << std::endl; + std::cout << "-----------------/! \\---------------" << std::endl; + } + + std::cout << "-----------------/! \\---------------" << std::endl; + std::cout << "Test finished!" << std::endl; + std::cout << "Success rate: " << success_counter << "/" << test_number << std::endl; + std::cout << "-----------------/! \\---------------" << std::endl; + } + } +} + +void DirectionalCoupler_tb_run() +{ + // Apply SPECS resolution before creating any device + specsGlobalConfig.applyEngineResolution(); + + + spx::oa_signal_type IN1, IN2, IN3, IN4, OUT1, OUT2; + spx::oa_signal_type TERM_r, TERM_w; + + // Unidirectional variant + // DirectionalCoupler uut("uut", 0.5, 0); + // uut.m_dc_through_coupling_power = 0.1; + // uut.m_dc_loss = 3.0103; + + // uut.p_in1(IN1); + // uut.p_in2(IN2); + // uut.p_out1(OUT1); + // uut.p_out2(OUT2); + + // Bidirectional variant + DirectionalCouplerBi uut("uut", 0.5, 0); + uut.m_dc_through_coupling_power = 0.1; + uut.m_dc_loss = 3.0103; + + uut.p0_in(IN1); + uut.p0_out(TERM_w); + uut.p1_in(IN2); + uut.p1_out(TERM_w); + uut.p2_in(TERM_r); + uut.p2_out(OUT1); + uut.p3_in(TERM_r); + uut.p3_out(OUT2); + + // Generic bidirectional variant + // Generic2x2Coupler uut("uut", 1-0.1, 3.0103); + // uut.ports_in[0]->bind(IN1); + // uut.ports_in[1]->bind(IN2); + // uut.ports_in[2]->bind(TERM_r); + // uut.ports_in[3]->bind(TERM_r); + // uut.ports_out[0]->bind(TERM_w); + // uut.ports_out[1]->bind(TERM_w); + // uut.ports_out[2]->bind(OUT1); + // uut.ports_out[3]->bind(OUT2); + + DirectionalCoupler_tb tb("tb"); + tb.IN1(IN1); + tb.IN2(IN2); + tb.OUT1(OUT1); + tb.OUT2(OUT2); + + // Open Trace file + std::string trace_filename = "traces/"; + trace_filename += "directional_coupler_tb"; + specsGlobalConfig.trace_filename = trace_filename; + + // Apply SPECS options specific to the testbench + specsGlobalConfig.simulation_mode = OpticalOutputPortMode::EVENT_DRIVEN; + specsGlobalConfig.trace_all_optical_nets = 0; + + Probe probe_dc_1("probe_dc_1",specsGlobalConfig.default_trace_file); + probe_dc_1.p_in(OUT1); + Probe probe_dc_2("probe_dc_2",specsGlobalConfig.default_trace_file); + probe_dc_2.p_in(OUT2); + + // Run SPECS pre-simulation code + specsGlobalConfig.prepareSimulation(); + + // Start simulation + sc_start(); + + std::cout << std::endl << std::endl; + std::cout << ".vcd trace file: " << specsGlobalConfig.trace_filename << std::endl; + + sc_close_vcd_trace_file(specsGlobalConfig.default_trace_file); +} diff --git a/src/tb/directional_coupler_tb.h b/src/tb/directional_coupler_tb.h new file mode 100644 index 0000000..c137b31 --- /dev/null +++ b/src/tb/directional_coupler_tb.h @@ -0,0 +1,31 @@ +#pragma once + +#include <directional_coupler.h> +#include <optical_signal.h> +#include <systemc.h> +#include <probe.h> +#include <specs.h> + +SC_MODULE(DirectionalCoupler_tb) +{ +public: + spx::oa_port_out_type IN1; + spx::oa_port_out_type IN2; + spx::oa_port_in_type OUT1; + spx::oa_port_in_type OUT2; + + void run_1(); + void monitor(); + SC_CTOR(DirectionalCoupler_tb) + { + SC_HAS_PROCESS(DirectionalCoupler_tb); + + SC_THREAD(run_1); + + SC_THREAD(monitor); + sensitive << IN1 << IN2 << OUT1 << OUT2; + } +}; + +void DirectionalCoupler_tb_run(); + diff --git a/src/tb/freqsweep_tb.cpp b/src/tb/freqsweep_tb.cpp new file mode 100644 index 0000000..f44aa34 --- /dev/null +++ b/src/tb/freqsweep_tb.cpp @@ -0,0 +1,213 @@ +#include <ctime> +#include <iomanip> +#include <tb/freqsweep_tb.h> + +#include <cstdlib> +#include <unistd.h> + +#include "time_monitor.h" + +#include "general_utils.h" + +/* ----------------------------------------------------------------------------- * + This testbench is called freqsweep because it is capable of this + type of simulation, but it is also possible to set it as a time-domain + simulation depending on the mode chosen when calling SPECS. Example: + + specs -t ac_add_drop -m fd -> will perform the frequency sweep + specs -t ac_add_drop -m td -> will perform the time domain simulation + +/ ----------------------------------------------------------------------------- */ + +void freqsweep_tb::run_1() +{ + if (specsGlobalConfig.simulation_mode == OpticalOutputPortMode::FREQUENCY_DOMAIN) + { + auto lambda_center = 1550.3e-9; + auto lambda_span = 1e-9; + auto dlambda = 0.002e-9; + auto lambda_min = lambda_center - lambda_span/2; + auto lambda_max = lambda_center + lambda_span/2; + // lambda_min = 1550.250e-9; + // lambda_max = 1550.303e-9; + //wait(lambda_min * 1e9, SC_SEC); + + wait(SC_ZERO_TIME); + cout << "----------------------------" <<endl; + cout << "Starting sweep" << endl; + for (auto lambda = lambda_min; lambda < lambda_max + dlambda; lambda += dlambda) + { + cout << setprecision(7) << lambda * 1e9 << "nm" << endl; + IN->write(OpticalSignal(1, lambda)); + wait(dlambda, SC_SEC); + } + } else { + for (int i = 0; i < 1; ++i) + { + auto lambda = 1550.302e-9; + IN->write(OpticalSignal(1,lambda)); + wait(1, SC_NS); + IN->write(OpticalSignal(0, lambda)); + wait(1, SC_NS); + } + } + + while (true) { wait(); } +} + +void freqsweep_tb::monitor() +{ + unsigned int event_counter = 0; + unsigned int success_counter = 0; + const unsigned int test_number = 3; + while(true) + { + wait(); + continue; + } +} + +void freqsweep_tb_run_add_drop() +{ + specsGlobalConfig.applyEngineResolution(); + //specsGlobalConfig.oop_configs[0]->m_mode = OpticalOutputPortMode::EVENT_DRIVEN; + //specsGlobalConfig.oop_configs[0]->m_mode = OpticalOutputPortMode::FREQUENCY_DOMAIN; + + // First test for the LBR paper to DAC + // Single ring resonator, compare the response to theoretical + // Also compare time of simulation wrt photontorch for same ring. + + // Characteristics: + // Add-drop ring + // Internal wg length (cm): + // Internal wg loss (dB/cm): + // Internal wg neff: + // Internal wg ng: + // DC ratio : 0.15 cross, 0.85 through + // DC coupling loss (dB) : 0 + // Total length for resonance: lambda/2neff + double neff = 1.0; + double loss_db_cm = 1.0; + double coupling_through = 0.85; + + spx::oa_signal_type IN, T_OUT, X_OUT, X_TERM; + spx::oa_signal_type INNER_RING[4]; + + freqsweep_tb tb1("tb1"); + tb1.IN(IN); + tb1.OUT(X_OUT); + + DirectionalCoupler dc1("dc1", coupling_through, 0); + dc1.p_in1(INNER_RING[0]); + dc1.p_out1(INNER_RING[1]); + dc1.p_in2(IN); + dc1.p_out2(T_OUT); + + Waveguide wg1("wg1", 100.0*1550.0e-6/(2*neff), loss_db_cm, neff, neff); + wg1.p_in(INNER_RING[1]); + wg1.p_out(INNER_RING[2]); + + Waveguide wg2("wg2", 100.0*1550.0e-6/(2*neff), loss_db_cm, neff, neff); + wg2.p_in(INNER_RING[3]); + wg2.p_out(INNER_RING[0]); + + DirectionalCoupler dc2("dc2", coupling_through, 0); + dc2.p_in1(X_TERM); + dc2.p_out1(X_OUT); + dc2.p_in2(INNER_RING[2]); + dc2.p_out2(INNER_RING[3]); + + Probe pthrough("ptrough"); + pthrough.p_in(T_OUT); + + Probe pcross("pcross"); + pcross.p_in(X_OUT); + + // Open Trace file + std::string trace_filename = "traces/"; + trace_filename += "freqsweep_tb"; + specsGlobalConfig.trace_filename = trace_filename; + + // Apply SPECS options specific to the testbench + // could have forced frequency domain like this, but taking command line input instead + // specsGlobalConfig.simulation_mode = OpticalOutputPortMode::FREQUENCY_DOMAIN; + specsGlobalConfig.trace_all_optical_nets = 0; + + // Run SPECS pre-simulation code + specsGlobalConfig.prepareSimulation(); + + // Start simulation + sc_start(); + + std::cout << std::endl << std::endl; + std::cout << ".vcd trace file: " << specsGlobalConfig.trace_filename << std::endl; + + sc_close_vcd_trace_file(specsGlobalConfig.default_trace_file); +} + +// void freqsweep_tb_run_crow() +// { +// if (specsGlobalConfig.oop_configs[0]->m_mode == OpticalOutputPortMode::FREQUENCY_DOMAIN) +// specsGlobalConfig.engine_timescale = SPECSConfig::ONE_FS; + +// specsGlobalConfig.applyEngineResolution(); + +// sc_signal<OpticalSignal> IN("IN"), T_OUT("T_OUT"), X_OUT("X_OUT"), ADD("ADD"); + +// freqsweep_tb tb1("tb1"); +// tb1.IN(IN); +// tb1.IN(IN); +// tb1.OUT(T_OUT); + +// // pid_t pid = fork(); +// CROW *pc; +// // if(pid) +// pc = new CROW("crow", nrings); +// // else +// // pc = new CROW("crow", 5); +// pc->p_in(IN); +// pc->p_add(ADD); +// pc->p_out_t(T_OUT); +// pc->p_out_d(X_OUT); + +// Probe pthrough("ptrough"); +// pthrough.p_in(T_OUT); +// // +// Probe pcross("pcross"); +// pcross.p_in(X_OUT); + +// // shared_ptr<TimeMonitor> tm; +// // if (specsGlobalConfig.oop_configs[0]->m_mode == OpticalOutputPortMode::FREQUENCY_DOMAIN) +// // tm = make_shared<TimeMonitor>("TM", 0, 0.01); +// // else +// // tm = make_shared<TimeMonitor>("TM", 1e-14, 0.5); + +// // // Open Trace file +// // sc_trace_file *Tf; +// // std::time_t now = std::time(nullptr); +// // char mbstr[100]; +// // std::strftime(mbstr, sizeof(mbstr), "%F-%H-%M-%S-", std::localtime(&now)); +// // +// // std::string trace_filename = "traces/"; +// // //trace_filename += mbstr; +// // trace_filename += "freqsweep_tb"; + +// // auto engineTime = std::pow(10, 15+specsGlobalConfig.engine_timescale); +// // Tf = sc_create_vcd_trace_file(trace_filename.c_str()); +// // ((sc_trace_file *)Tf)->set_time_unit(engineTime, SC_FS); +// // sc_trace(Tf, IN, "IN"); +// // sc_trace(Tf, X_OUT, "X_OUT"); +// // sc_trace(Tf, T_OUT, "T_OUT"); + +// if (specsGlobalConfig.trace_filename.empty()) +// specsGlobalConfig.trace_filename = "traces/crow_tb"; + +// // Start simulation +// specsGlobalConfig.prepareSimulation(); +// sc_start(); // run until sc_stop() + +// std::cout << std::endl << std::endl; +// std::cout << ".vcd trace file: " << specsGlobalConfig.trace_filename << std::endl; + +// sc_close_vcd_trace_file(specsGlobalConfig.default_trace_file); +// } diff --git a/src/tb/freqsweep_tb.h b/src/tb/freqsweep_tb.h new file mode 100644 index 0000000..d5a328c --- /dev/null +++ b/src/tb/freqsweep_tb.h @@ -0,0 +1,33 @@ +#pragma once + +#include <optical_signal.h> +#include <systemc.h> +#include <waveguide.h> +#include <directional_coupler.h> +#include <probe.h> +#include <crow.h> +#include <specs.h> + +SC_MODULE(freqsweep_tb) +{ +public: + spx::oa_port_out_type IN; + spx::oa_port_in_type OUT; + + void run_1(); + void monitor(); + SC_CTOR(freqsweep_tb) + { + SC_HAS_PROCESS(freqsweep_tb); + + SC_THREAD(run_1); + + SC_THREAD(monitor); + sensitive << IN << OUT; + } +}; + +//void freqsweep_tb_run(); +void freqsweep_tb_run_add_drop(); +void freqsweep_tb_run_crow(); + diff --git a/src/tb/lambda_tb.cpp b/src/tb/lambda_tb.cpp new file mode 100644 index 0000000..96a5084 --- /dev/null +++ b/src/tb/lambda_tb.cpp @@ -0,0 +1,102 @@ +#include <ctime> +#include <iomanip> +#include <tb/lambda_tb.h> + +#include "general_utils.h" +#include "devices/generic_waveguide.h" + +void lambda_tb::run_1() +{ + // IN1.write(OpticalSignal(sqrt(2.0), 1550e-9)); + // wait(0, SC_FS); + // IN2.write(OpticalSignal(sqrt(2.0), 1660e-9)); + // while(true) {wait();} + wait(1,SC_SEC); + sc_stop(); +} + +void lambda_tb::monitor() +{ + unsigned int event_counter = 0; + unsigned int success_counter = 0; + const unsigned int test_number = 0; + while(true) + { + wait(); + event_counter++; + std::cout << sc_time_stamp() << ":" << std::endl + << "\tOUT: " << OUT.read() << std::endl + << "\tCOUNT: " << event_counter << std::endl; + } + +} + +void lambda_tb_run() +{ + // Apply SPECS resolution before creating any device + specsGlobalConfig.applyEngineResolution(); + + spx::oa_signal_type I1, I2, YOUT, WGOUT; + spx::oa_signal_type DCO1, DCO2, DCI1, DCI2; + + CWSource cw1("cw1"); + cw1.setWavelength(1550e-9); + cw1.setPower(2); + cw1.enable.write(SC_LOGIC_1); + cw1.p_out(I1); + + CWSource cw2("cw2"); + cw2.setWavelength(1660e-9); + cw2.setPower(2); + cw2.enable.write(SC_LOGIC_1); + cw2.p_out(I2); + + Merger merg1("merg1"); + merg1.p_in1(I1); + merg1.p_in2(I2); + merg1.p_out(YOUT); + + Waveguide wg1("wg1", 0.1, 0, 1, 1); + wg1.m_attenuation_dB_cm = 0; + wg1.p_in(YOUT); + wg1.p_out(DCI1); + + DirectionalCoupler dc1("dc1"); + dc1.p_in1(DCI1); + dc1.p_in2(DCI2); + dc1.p_out1(DCO1); + dc1.p_out2(DCO2); + + Waveguide wg2("wg2", 100*1001*1550e-9/(2), 0, 1, 1); + wg2.p_in(DCO2); + wg2.p_out(DCI2); + + lambda_tb tb("tb"); + tb.OUT(DCO1); + // tb.IN1(I1); + // tb.IN2(I2); + + // Open Trace file + std::string trace_filename = "traces/"; + trace_filename += "lambda_tb"; + specsGlobalConfig.trace_filename = trace_filename; + + // Apply SPECS options specific to the testbench + specsGlobalConfig.simulation_mode = OpticalOutputPortMode::EVENT_DRIVEN; + specsGlobalConfig.trace_all_optical_nets = 0; + + MLambdaProbe probe("probe_lambda", {1550e-9, 1650e-9, 1660e-9}); + // Probe probe("test_probe",specsGlobalConfig.default_trace_file); + probe.p_in(DCO1); + + // Run SPECS pre-simulation code + specsGlobalConfig.prepareSimulation(); + + // Start simulation + sc_start(); + + std::cout << std::endl << std::endl; + std::cout << ".vcd trace file: " << specsGlobalConfig.trace_filename << std::endl; + + sc_close_vcd_trace_file(specsGlobalConfig.default_trace_file); +} diff --git a/src/tb/lambda_tb.h b/src/tb/lambda_tb.h new file mode 100644 index 0000000..a5dc203 --- /dev/null +++ b/src/tb/lambda_tb.h @@ -0,0 +1,31 @@ +#pragma once + +#include <optical_signal.h> +#include <systemc.h> +#include <waveguide.h> +#include <merger.h> +#include <directional_coupler.h> +#include <cw_source.h> +#include <probe.h> +#include <specs.h> + +SC_MODULE(lambda_tb) +{ +public: + sc_in<OpticalSignal> OUT; + // sc_out<OpticalSignal> IN1, IN2; + + void run_1(); + void monitor(); + SC_CTOR(lambda_tb) + { + SC_HAS_PROCESS(lambda_tb); + + SC_THREAD(run_1); + + SC_THREAD(monitor); + sensitive << OUT; + } +}; + +void lambda_tb_run(); diff --git a/src/tb/merger_tb.cpp b/src/tb/merger_tb.cpp new file mode 100644 index 0000000..1c86643 --- /dev/null +++ b/src/tb/merger_tb.cpp @@ -0,0 +1,126 @@ +#include <ctime> +#include <iomanip> +#include <tb/merger_tb.h> + +#include "general_utils.h" + +void Merger_tb::run_1() +{ + IN1->write(OpticalSignal(1.0, 1550e-9)); + wait(100, SC_MS); + IN2->write(OpticalSignal(1.0, 1550e-9)); + wait(100, SC_MS); + IN1->write(OpticalSignal(sqrt(2.0), 1550e-9)); + IN2->write(OpticalSignal(sqrt(2.0), 1550e-9)); + wait(100, SC_MS); +} + +void Merger_tb::monitor() +{ + unsigned int event_counter = 0; + unsigned int success_counter = 0; + const unsigned int test_number = 4; + while(true) + { + wait(); + event_counter++; + std::cout << sc_time_stamp() << ":" << std::endl + << "\tIN1: " << IN1->read() << std::endl + << "\tIN2: " << IN2->read() << std::endl + << "\tOUT: " << OUT->read() << std::endl + << "\tCOUNT: " << event_counter << std::endl; + if(event_counter == 2) + { + if (is_close(norm(OUT->read().m_field), 0.5, 1e-4)) + success_counter++; + else + { + std::cout << "-----------------/! \\---------------" << std::endl; + std::cout << "Failure!" << std::endl; + std::cout << "Expected 0.5W as output power!" << std::endl; + std::cout << "-----------------/! \\---------------" << std::endl; + } + if (is_close(arg(OUT->read().m_field), 0, 1e-4)) + success_counter++; + else + { + std::cout << "-----------------/! \\---------------" << std::endl; + std::cout << "Failure!" << std::endl; + std::cout << "Expected 0 as output phase!" << std::endl; + std::cout << "-----------------/! \\---------------" << std::endl; + } + } + if(event_counter == 4) + { + if (is_close(norm(OUT->read().m_field), 2, 1e-4)) + success_counter++; + else + { + std::cout << "-----------------/! \\---------------" << std::endl; + std::cout << "Failure!" << std::endl; + std::cout << "Expected 2W as output power!" << std::endl; + std::cout << "-----------------/! \\---------------" << std::endl; + } + } + if(event_counter == 6) + { + if (is_close(norm(OUT->read().m_field), 4, 1e-4)) + success_counter++; + else + { + std::cout << "-----------------/! \\---------------" << std::endl; + std::cout << "Failure!" << std::endl; + std::cout << "Expected 2W as output power!" << std::endl; + std::cout << "-----------------/! \\---------------" << std::endl; + } + + std::cout << "-----------------/! \\---------------" << std::endl; + std::cout << "Test finished!" << std::endl; + std::cout << "Success rate: " << success_counter << "/" << test_number << std::endl; + std::cout << "-----------------/! \\---------------" << std::endl; + } + } +} + +void Merger_tb_run() +{ + // Apply SPECS resolution before creating any device + specsGlobalConfig.applyEngineResolution(); + + spx::oa_signal_type IN1, IN2, OUT; + + Merger uut("uut", 3.0103); + uut.m_attenuation_dB = 0; + uut.p_in1(IN1); + uut.p_in2(IN2); + uut.p_out(OUT); + + Merger_tb tb("tb"); + tb.IN1(IN1); + tb.IN2(IN2); + tb.OUT(OUT); + + // Open Trace file + // sc_trace_file *Tf; + std::string trace_filename = "traces/"; + trace_filename += "merger_tb"; + specsGlobalConfig.trace_filename = trace_filename; + + // Apply SPECS options specific to the testbench + specsGlobalConfig.simulation_mode = OpticalOutputPortMode::EVENT_DRIVEN; + specsGlobalConfig.trace_all_optical_nets = 0; + + Probe probe_merger("probe_merger",specsGlobalConfig.default_trace_file); + probe_merger.p_in(OUT); + + // Run SPECS pre-simulation code + specsGlobalConfig.prepareSimulation(); + + // Start simulation + sc_start(); + + std::cout << std::endl << std::endl; + std::cout << ".vcd trace file: " << specsGlobalConfig.trace_filename << std::endl; + + sc_close_vcd_trace_file(specsGlobalConfig.default_trace_file); +} diff --git a/src/tb/merger_tb.h b/src/tb/merger_tb.h new file mode 100644 index 0000000..a71fd2a --- /dev/null +++ b/src/tb/merger_tb.h @@ -0,0 +1,30 @@ +#pragma once + +#include <merger.h> +#include <optical_signal.h> +#include <systemc.h> +#include <probe.h> +#include <specs.h> + +SC_MODULE(Merger_tb) +{ +public: + spx::oa_port_out_type IN1; + spx::oa_port_out_type IN2; + spx::oa_port_in_type OUT; + + void run_1(); + void monitor(); + SC_CTOR(Merger_tb) + { + SC_HAS_PROCESS(Merger_tb); + + SC_THREAD(run_1); + + SC_THREAD(monitor); + sensitive << IN1 << IN2 << OUT; + } +}; + +void Merger_tb_run(); + diff --git a/src/tb/mesh_tb.cpp b/src/tb/mesh_tb.cpp new file mode 100644 index 0000000..9effd11 --- /dev/null +++ b/src/tb/mesh_tb.cpp @@ -0,0 +1,130 @@ +#include <ctime> +#include <iomanip> +#include <tb/mesh_tb.h> + +#include "general_utils.h" + +void mesh_tb::run_1() +{ + IN->write(OpticalSignal(sqrt(1.0), 1550e-9)); + vtheta.write(M_PI); + vphi.write(1); + wait(1, SC_NS); + // vtheta.write(M_PI_2); + // wait(1, SC_NS); + // vtheta.write(M_PI); + // wait(1, SC_NS); + // vphi.write(1); + // wait(1, SC_NS); + + while (true) { wait(); } +} + +void mesh_tb::monitor() +{ + while(true) + { + wait(); + std::cout << sc_time_stamp() << ":" << std::endl + << "\tIN: " << IN->read() << std::endl + << "\tPHI: " << vphi.read() << std::endl + << "\tTHETA: " << vtheta.read() << std::endl + << "\tOUT1: " << OUT1->read() << std::endl + << "\tOUT2: " << OUT2->read() << std::endl + << "\tOUT3: " << OUT3->read() << std::endl + << "\tOUT4: " << OUT4->read() << std::endl + << "\tOUT5: " << OUT5->read() << std::endl; + } + +} + +void mesh_tb_run() +{ + // Apply SPECS resolution before creating any device + specsGlobalConfig.applyEngineResolution(); + + spx::oa_signal_type SIG, ZERO, OUT1, OUT2, OUT3, OUT4, OUT5; + sc_signal<double> vphi,vtheta,e_zero; + + Clements mesh1("mesh1", 5, 1, 0, 0, 0, 0, 1); + mesh1.p_in[0]->bind(SIG); + mesh1.p_in[1]->bind(SIG); + mesh1.p_in[2]->bind(SIG); + mesh1.p_in[3]->bind(SIG); + mesh1.p_in[4]->bind(SIG); + mesh1.p_out[0]->bind(OUT1); + mesh1.p_out[1]->bind(OUT2); + mesh1.p_out[2]->bind(OUT3); + mesh1.p_out[3]->bind(OUT4); + mesh1.p_out[4]->bind(OUT5); + + mesh1.p_vphi[0]->bind(e_zero); + mesh1.p_vtheta[0]->bind(vtheta); + + mesh1.p_vphi[1]->bind(e_zero); + mesh1.p_vtheta[1]->bind(e_zero); + + mesh1.p_vphi[2]->bind(e_zero); + mesh1.p_vtheta[2]->bind(vtheta); + + mesh1.p_vphi[3]->bind(e_zero); + mesh1.p_vtheta[3]->bind(e_zero); + + mesh1.p_vphi[4]->bind(e_zero); + mesh1.p_vtheta[4]->bind(e_zero); + + mesh1.p_vphi[5]->bind(e_zero); + mesh1.p_vtheta[5]->bind(e_zero); + + mesh1.p_vphi[6]->bind(e_zero); + mesh1.p_vtheta[6]->bind(e_zero); + + mesh1.p_vphi[7]->bind(e_zero); + mesh1.p_vtheta[7]->bind(e_zero); + + mesh1.p_vphi[8]->bind(e_zero); + mesh1.p_vtheta[8]->bind(e_zero); + + mesh1.p_vphi[9]->bind(e_zero); + mesh1.p_vtheta[9]->bind(e_zero); + + mesh1.init(); + + mesh_tb tb("tb"); + tb.IN(SIG); + tb.OUT1(OUT1); + tb.OUT2(OUT2); + tb.OUT3(OUT3); + tb.OUT4(OUT4); + tb.OUT5(OUT5); + tb.vphi(vphi); + tb.vtheta(vtheta); + + // Open Trace file + std::string trace_filename = "traces/"; + trace_filename += "mesh_tb"; + specsGlobalConfig.trace_filename = trace_filename; + + // Apply SPECS options specific to the testbench + specsGlobalConfig.simulation_mode = OpticalOutputPortMode::EVENT_DRIVEN; + specsGlobalConfig.trace_all_optical_nets = 0; + + + Probe probe_mzi_1("probe_mzi_1",specsGlobalConfig.default_trace_file); + probe_mzi_1.p_in(OUT1); + Probe probe_mzi_2("probe_mzi_2",specsGlobalConfig.default_trace_file); + probe_mzi_2.p_in(OUT2); + Probe probe_in("probe_in",specsGlobalConfig.default_trace_file); + probe_in.p_in(SIG); + + // Run SPECS pre-simulation code + specsGlobalConfig.prepareSimulation(); + + // Start simulation + sc_start(); + + std::cout << std::endl << std::endl; + std::cout << ".vcd trace file: " << specsGlobalConfig.trace_filename << std::endl; + + sc_close_vcd_trace_file(specsGlobalConfig.default_trace_file); +} diff --git a/src/tb/mesh_tb.h b/src/tb/mesh_tb.h new file mode 100644 index 0000000..1e7e3dd --- /dev/null +++ b/src/tb/mesh_tb.h @@ -0,0 +1,29 @@ +#pragma once + +#include <optical_signal.h> +#include <systemc.h> +#include <probe.h> +#include <specs.h> +#include <clements.h> + +SC_MODULE(mesh_tb) +{ +public: + spx::oa_port_out_type IN; + spx::oa_port_in_type OUT1, OUT2, OUT3, OUT4, OUT5; + sc_out<double> vphi,vtheta; + + void run_1(); + void monitor(); + SC_CTOR(mesh_tb) + { + SC_HAS_PROCESS(mesh_tb); + + SC_THREAD(run_1); + + SC_THREAD(monitor); + sensitive << IN << OUT1 << OUT2 << OUT3 << OUT4 << OUT5 << vphi << vtheta; + } +}; + +void mesh_tb_run(); diff --git a/src/tb/mzi_tb.cpp b/src/tb/mzi_tb.cpp new file mode 100644 index 0000000..2b9905a --- /dev/null +++ b/src/tb/mzi_tb.cpp @@ -0,0 +1,86 @@ +#include <ctime> +#include <iomanip> +#include <tb/mzi_tb.h> + +#include "general_utils.h" + +void mzi_tb::run_1() +{ + IN->write(OpticalSignal(sqrt(1.0), 1550e-9)); + wait(1, SC_NS); + vtheta.write(M_PI_2); + wait(1, SC_NS); + vtheta.write(M_PI); + wait(1, SC_NS); + vphi.write(1); + wait(1, SC_NS); + + while (true) { wait(); } +} + +void mzi_tb::monitor() +{ + while(true) + { + wait(); + std::cout << sc_time_stamp() << ":" << std::endl + << "\tIN: " << IN->read() << std::endl + << "\tPHI: " << vphi.read() << std::endl + << "\tTHETA: " << vtheta.read() << std::endl + << "\tOUT1: " << OUT1->read() << std::endl + << "\tOUT2: " << OUT2->read() << std::endl; + } + +} + +void MZI_tb_run() +{ + // Apply SPECS resolution before creating any device + specsGlobalConfig.applyEngineResolution(); + + spx::oa_signal_type IN1, IN2, OUT1, OUT2; + spx::ea_signal_type vphi,vtheta; + + MZI mzi1("mzi1",0,0,0,0,0,1); + mzi1.p_in1(IN1); + mzi1.p_in2(IN2); + mzi1.p_out1(OUT1); + mzi1.p_out2(OUT2); + mzi1.p_vphi(vphi); + mzi1.p_vtheta(vtheta); + + mzi_tb tb("tb"); + tb.IN(IN1); + tb.OUT1(OUT1); + tb.OUT2(OUT2); + tb.vphi(vphi); + tb.vtheta(vtheta); + + // Open Trace file + std::string trace_filename = "traces/"; + trace_filename += "mzi_tb"; + specsGlobalConfig.trace_filename = trace_filename; + + // Apply SPECS options specific to the testbench + specsGlobalConfig.simulation_mode = OpticalOutputPortMode::EVENT_DRIVEN; + specsGlobalConfig.trace_all_optical_nets = 0; + + + Probe probe_mzi_1("probe_mzi_1",specsGlobalConfig.default_trace_file); + probe_mzi_1.p_in(OUT1); + Probe probe_mzi_2("probe_mzi_2",specsGlobalConfig.default_trace_file); + probe_mzi_2.p_in(OUT2); + Probe probe_in("probe_in",specsGlobalConfig.default_trace_file); + probe_in.p_in(IN1); + + // Run SPECS pre-simulation code + specsGlobalConfig.prepareSimulation(); + + // Start simulation + sc_start(); + + std::cout << std::endl << std::endl; + std::cout << ".vcd trace file: " << specsGlobalConfig.trace_filename << std::endl; + + sc_close_vcd_trace_file(specsGlobalConfig.default_trace_file); +} diff --git a/src/tb/mzi_tb.h b/src/tb/mzi_tb.h new file mode 100644 index 0000000..16ed624 --- /dev/null +++ b/src/tb/mzi_tb.h @@ -0,0 +1,31 @@ +#pragma once + +#include <optical_signal.h> +#include <systemc.h> +#include <waveguide.h> +#include <directional_coupler.h> +#include <mzi.h> +#include <probe.h> +#include <specs.h> + +SC_MODULE(mzi_tb) +{ +public: + spx::oa_port_out_type IN; + spx::oa_port_in_type OUT1, OUT2; + sc_out<double> vphi,vtheta; + + void run_1(); + void monitor(); + SC_CTOR(mzi_tb) + { + SC_HAS_PROCESS(mzi_tb); + + SC_THREAD(run_1); + + SC_THREAD(monitor); + sensitive << IN << OUT1 << OUT2 << vphi << vtheta; + } +}; + +void MZI_tb_run(); diff --git a/src/tb/pcm_device_tb.cpp b/src/tb/pcm_device_tb.cpp new file mode 100644 index 0000000..b279e6c --- /dev/null +++ b/src/tb/pcm_device_tb.cpp @@ -0,0 +1,129 @@ +#include <ctime> +#include <iomanip> +#include <tb/pcm_device_tb.h> + +#include "general_utils.h" + +void PCMElement_tb::run_1() +{ + IN->write(OpticalSignal(sqrt(1.0e-3), 1.55e-6)); + wait(10, SC_MS); + IN->write(OpticalSignal(sqrt(2*1e-3), 1.55e-6)); // to 2W + wait(10, SC_MS); + IN->write(OpticalSignal(0, 1.55e-6)); + wait(10, SC_MS); + IN->write(OpticalSignal(sqrt(1.0e-3), 1.55e-6)); + wait(10, SC_MS); + IN->write(OpticalSignal(sqrt(2*1.0e-3), 1.55e-6)); + wait(10, SC_MS); + IN->write(OpticalSignal(0, 1.55e-6)); + wait(10, SC_MS); + IN->write(OpticalSignal(sqrt(1.0e-3), 1.55e-6)); + + + while (true) { wait(); } +} + +void PCMElement_tb::monitor() +{ + unsigned int event_counter = 0; + unsigned int success_counter = 0; + const unsigned int test_number = 3; + while(true) + { + wait(); + event_counter++; + std::cout << sc_time_stamp() << ":" << std::endl + << "\tIN: " << IN->read() << std::endl + << "\tOUT: " << OUT->read() << std::endl + << "\tCOUNT: " << event_counter << std::endl; + + if(event_counter == 2) + { + if (is_close(norm(OUT->read().m_field), 0.000850, 1e-8)) + success_counter++; + else + { + std::cout << "-----------------/! \\---------------" << std::endl; + std::cout << "Failure!" << std::endl; + std::cout << "Expected 0.850mW as output power!" << std::endl; + std::cout << "-----------------/! \\---------------" << std::endl; + } + } + if(event_counter == 8) + { + if (is_close(norm(OUT->read().m_field), 0.000854758, 1e-8)) + success_counter++; + else + { + std::cout << "-----------------/! \\---------------" << std::endl; + std::cout << "Failure!" << std::endl; + std::cout << "Expected 0.854mW as output power!" << std::endl; + std::cout << "-----------------/! \\---------------" << std::endl; + } + } + if(event_counter == 14) + { + if (is_close(norm(OUT->read().m_field), 0.000859495, 1e-8)) + success_counter++; + else + { + std::cout << "-----------------/! \\---------------" << std::endl; + std::cout << "Failure!" << std::endl; + std::cout << "Expected 0.859mW as output power!" << std::endl; + std::cout << "-----------------/! \\---------------" << std::endl; + } + + std::cout << "-----------------/! \\---------------" << std::endl; + std::cout << "Test finished!" << std::endl; + std::cout << "Success rate: " << success_counter << "/" << test_number << std::endl; + std::cout << "-----------------/! \\---------------" << std::endl; + } + } +} + +void PCMElement_tb_run() +{ + // Apply SPECS resolution before creating any device + specsGlobalConfig.applyEngineResolution(); + + spx::oa_signal_type IN, OUT; + + PCMElement pcm("pcm", 25e-6, 63, 0); + pcm.p_in(IN); + pcm.p_out(OUT); + + PCMElement_tb tb("tb"); + tb.IN(IN); + tb.OUT(OUT); + + // Open Trace file + + std::string trace_filename = "traces/"; + trace_filename += "pcm_device_tb"; + specsGlobalConfig.trace_filename = trace_filename; + + Probe probe_in("in",specsGlobalConfig.default_trace_file); + probe_in.p_in(IN); + + Probe probe_out("out",specsGlobalConfig.default_trace_file); + probe_out.p_in(OUT); + + // Apply SPECS options specific to the testbench + specsGlobalConfig.simulation_mode = OpticalOutputPortMode::EVENT_DRIVEN; + specsGlobalConfig.trace_all_optical_nets = 0; + + // Run SPECS pre-simulation code + specsGlobalConfig.prepareSimulation(); + + // extra traces should come after prepareSimulation + sc_trace(specsGlobalConfig.default_trace_file, pcm.m_state, "STATE"); + + // Start simulation + sc_start(); + + std::cout << std::endl << std::endl; + std::cout << ".vcd trace file: " << specsGlobalConfig.trace_filename << std::endl; + + sc_close_vcd_trace_file(specsGlobalConfig.default_trace_file); +} diff --git a/src/tb/pcm_device_tb.h b/src/tb/pcm_device_tb.h new file mode 100644 index 0000000..a9b7195 --- /dev/null +++ b/src/tb/pcm_device_tb.h @@ -0,0 +1,29 @@ +#pragma once + +#include <systemc.h> + +#include <optical_signal.h> +#include <pcm_device.h> +#include <probe.h> +#include <specs.h> + +SC_MODULE(PCMElement_tb) +{ +public: + spx::oa_port_out_type IN; + spx::oa_port_in_type OUT; + + void run_1(); + void monitor(); + SC_CTOR(PCMElement_tb) + { + SC_HAS_PROCESS(PCMElement_tb); + + SC_THREAD(run_1); + + SC_THREAD(monitor); + sensitive << IN << OUT; + } +}; + +void PCMElement_tb_run(); diff --git a/src/tb/phase_shifter_tb.cpp b/src/tb/phase_shifter_tb.cpp new file mode 100644 index 0000000..5369e7c --- /dev/null +++ b/src/tb/phase_shifter_tb.cpp @@ -0,0 +1,129 @@ +#include <ctime> +#include <iomanip> +#include <tb/phase_shifter_tb.h> + +#include "general_utils.h" +#include "specs.h" + +void ps_tb::run_1() +{ + V_PS.write(1.0); + wait(SC_ZERO_TIME); + IN1->write(OpticalSignal(sqrt(1.0), 1550e-9)); + IN2->write(OpticalSignal(sqrt(1.0), 1660e-9)); + wait(100,SC_MS); + V_PS.write(2.0); + wait(100, SC_MS); + + while (true) { wait(); } +} + +void ps_tb::monitor() +{ + unsigned int event_counter = 0; + unsigned int success_counter = 0; + const unsigned int test_number = 3; + while(true) + { + wait(); + event_counter++; + std::cout << sc_time_stamp() << ":" << std::endl + << "\tIN1: " << IN1->read() << std::endl + << "\tIN2: " << IN2->read() << std::endl + << "\tOUT: " << OUT->read() << std::endl + << "\tCOUNT: " << event_counter << std::endl; + + if(event_counter == 2) + { + if (is_close(abs(OUT->read().m_field), 0.630210, 1e-4)) + success_counter++; + else + { + std::cout << "-----------------/! \\---------------" << std::endl; + std::cout << "Failure!" << std::endl; + std::cout << "Expected 0.630210W as output field!" << std::endl; + std::cout << "-----------------/! \\---------------" << std::endl; + } + } + if(event_counter == 4) + { + if (is_close(arg(OUT->read().m_field), 2, 1e-4)) + success_counter++; + else + { + std::cout << "-----------------/! \\---------------" << std::endl; + std::cout << "Failure!" << std::endl; + std::cout << "Expected 2 rad as output phase!" << std::endl; + std::cout << "-----------------/! \\---------------" << std::endl; + } + } + if(event_counter == 5) + { + if (is_close(arg(OUT->read().m_field), 2, 1e-4)) + success_counter++; + else + { + std::cout << "-----------------/! \\---------------" << std::endl; + std::cout << "Failure!" << std::endl; + std::cout << "Expected 2 as output phase!" << std::endl; + std::cout << "-----------------/! \\---------------" << std::endl; + } + + std::cout << "-----------------/! \\---------------" << std::endl; + std::cout << "Test finished!" << std::endl; + std::cout << "Success rate: " << success_counter << "/" << test_number << std::endl; + std::cout << "-----------------/! \\---------------" << std::endl; + } + } + +} + +void ps_tb_run() +{ + // Apply SPECS resolution before creating any device + specsGlobalConfig.applyEngineResolution(); + + spx::oa_signal_type IN1, IN2, OUT, YOUT; + spx::ea_signal_type V_PS; + + Merger merg1("merg1"); + merg1.p_in1(IN1); + merg1.p_in2(IN2); + merg1.p_out(YOUT); + + PhaseShifter ps1("ps1", 1); + ps1.p_in(YOUT); + ps1.p_vin(V_PS); + ps1.p_out(OUT); + + // Connect testbench to uut + ps_tb tb("tb"); + tb.IN1(IN1); + tb.IN2(IN2); + tb.OUT(OUT); + tb.V_PS(V_PS); + + // Attach probes + MLambdaProbe probe_out("out", {1550e-9, 1660e-9}); + probe_out.p_in(OUT); + + // Open Trace file + std::string trace_filename = "traces/"; + trace_filename += "ps_tb"; + specsGlobalConfig.trace_filename = trace_filename; + + // Apply SPECS options specific to the testbench + specsGlobalConfig.simulation_mode = OpticalOutputPortMode::EVENT_DRIVEN; + specsGlobalConfig.trace_all_optical_nets = 0; + + // Run SPECS pre-simulation code + specsGlobalConfig.prepareSimulation(); + + // Start simulation + sc_start(); + + std::cout << std::endl << std::endl; + std::cout << ".vcd trace file: " << specsGlobalConfig.trace_filename << std::endl; + + sc_close_vcd_trace_file(specsGlobalConfig.default_trace_file); +} diff --git a/src/tb/phase_shifter_tb.h b/src/tb/phase_shifter_tb.h new file mode 100644 index 0000000..a59538d --- /dev/null +++ b/src/tb/phase_shifter_tb.h @@ -0,0 +1,32 @@ +#pragma once + +#include <optical_signal.h> +#include <systemc.h> +#include <waveguide.h> +#include <phaseshifter.h> +#include <merger.h> +#include <probe.h> +#include <specs.h> + +SC_MODULE(ps_tb) +{ +public: + spx::oa_port_out_type IN1; + spx::oa_port_out_type IN2; + sc_out<double> V_PS; + spx::oa_port_in_type OUT; + + void run_1(); + void monitor(); + SC_CTOR(ps_tb) + { + SC_HAS_PROCESS(ps_tb); + + SC_THREAD(run_1); + + SC_THREAD(monitor); + sensitive << IN1 << IN2 << OUT; + } +}; + +void ps_tb_run(); diff --git a/src/tb/ring_tb.cpp b/src/tb/ring_tb.cpp new file mode 100644 index 0000000..cc3aaf2 --- /dev/null +++ b/src/tb/ring_tb.cpp @@ -0,0 +1,85 @@ +#include <ctime> +#include <iomanip> +#include <tb/ring_tb.h> + +#include "general_utils.h" + +void ring_tb::run_1() +{ + IN.write(OpticalSignal(sqrt(1.0), 1550e-9)); + wait(10, SC_NS); + IN.write(OpticalSignal(0, 1550e-9)); + wait(10, SC_NS); + + IN.write(OpticalSignal(sqrt(1.0), 1550e-9)); + wait(10, SC_NS); + IN.write(OpticalSignal(0, 1550e-9)); + wait(10, SC_NS); + + while(true) + { + wait(); + } +} + +void ring_tb::monitor() +{ + while(true) + { + wait(); + std::cout << sc_time_stamp() << ":" << std::endl + << "\tIN: " << IN.read() << std::endl + << "\tOUT: " << OUT.read() << std::endl; + } + +} + +void Ring_tb_run() +{ + // Apply SPECS resolution before creating any device + specsGlobalConfig.applyEngineResolution(); + + double neff = 1.0; + double loss_db_cm = 0; + double coupling_through = 0.85; + + spx::oa_signal_type IN, OUT; + spx::oa_signal_type RING1, RING2; + + DirectionalCoupler dc1("dc1", coupling_through, 0); + dc1.p_in1(IN); + dc1.p_out1(OUT); + dc1.p_in2(RING1); + dc1.p_out2(RING2); + + Waveguide wg1("wg1", 1*100.0*1550.0e-6/(2*neff), loss_db_cm, neff, neff); + wg1.p_in(RING2); + wg1.p_out(RING1); + + ring_tb tb("tb"); + tb.IN(IN); + tb.OUT(OUT); + + // Open Trace file + std::string trace_filename = "traces/"; + trace_filename += "ring_tb"; + specsGlobalConfig.trace_filename = trace_filename; + + // Apply SPECS options specific to the testbench + specsGlobalConfig.simulation_mode = OpticalOutputPortMode::EVENT_DRIVEN; + specsGlobalConfig.trace_all_optical_nets = 0; + + Probe probe_ring("probe_ring",specsGlobalConfig.default_trace_file); + probe_ring.p_in(OUT); + + // Run SPECS pre-simulation code + specsGlobalConfig.prepareSimulation(); + + // Start simulation + sc_start(); + + std::cout << std::endl << std::endl; + std::cout << ".vcd trace file: " << specsGlobalConfig.trace_filename << std::endl; + + sc_close_vcd_trace_file(specsGlobalConfig.default_trace_file); +} diff --git a/src/tb/ring_tb.h b/src/tb/ring_tb.h new file mode 100644 index 0000000..b995513 --- /dev/null +++ b/src/tb/ring_tb.h @@ -0,0 +1,29 @@ +#pragma once + +#include <optical_signal.h> +#include <systemc.h> +#include <waveguide.h> +#include <directional_coupler.h> +#include <probe.h> +#include <specs.h> + +SC_MODULE(ring_tb) +{ +public: + sc_out<OpticalSignal> IN; + sc_in<OpticalSignal> OUT; + + void run_1(); + void monitor(); + SC_CTOR(ring_tb) + { + SC_HAS_PROCESS(ring_tb); + + SC_THREAD(run_1); + + SC_THREAD(monitor); + sensitive << IN << OUT; + } +}; + +void Ring_tb_run(); diff --git a/src/tb/splitter_tb.cpp b/src/tb/splitter_tb.cpp new file mode 100644 index 0000000..eeb3420 --- /dev/null +++ b/src/tb/splitter_tb.cpp @@ -0,0 +1,123 @@ +#include <ctime> +#include <iomanip> +#include <tb/splitter_tb.h> + +#include "general_utils.h" + +void Splitter_tb::run_1() +{ + IN->write(OpticalSignal(sqrt(1.0), 1550e-9)); + wait(100, SC_MS); + IN->write(OpticalSignal(-sqrt(1.0), 1550e-9)); + wait(100, SC_MS); + IN->write(OpticalSignal(sqrt(2.0), 1550e-9)); + wait(100, SC_MS); + IN->write(OpticalSignal(-sqrt(2.0), 1550e-9)); + wait(10, SC_PS); + IN->write(OpticalSignal(sqrt(3.0), 1550e-9)); + wait(100, SC_MS); + + wait(OUT1->value_changed_event()); + wait(1, SC_SEC); + sc_stop(); +} + +void Splitter_tb::monitor() +{ + unsigned int event_counter = 0; + unsigned int success_counter = 0; + const unsigned int test_number = 3; + while(true) + { + wait(); + event_counter++; + std::cout << sc_time_stamp() << ":" << std::endl + << "\tIN: " << IN->read() << std::endl + << "\tOUT1: " << OUT1->read() << std::endl + << "\tOUT2: " << OUT2->read() << std::endl + << "\tCOUNT: " << event_counter << std::endl; + + if(event_counter == 10) + { + if (is_close(norm(OUT1->read().m_field), 0.75, 1e-4)) + success_counter++; + else + { + std::cout << "-----------------/! \\---------------" << std::endl; + std::cout << "Failure!" << std::endl; + std::cout << "Expected 0.75W as output power!" << std::endl; + std::cout << "-----------------/! \\---------------" << std::endl; + } + + if (is_close(norm(OUT1->read().m_field), norm(OUT2->read().m_field), 1e-4)) + success_counter++; + else + { + std::cout << "-----------------/! \\---------------" << std::endl; + std::cout << "Failure!" << std::endl; + std::cout << "Expected same power in both ends!" << std::endl; + std::cout << "-----------------/! \\---------------" << std::endl; + } + + if (is_close(arg(OUT1->read().m_field), 0, 1e-4) && is_close(arg(OUT2->read().m_field), 0, 1e-4)) + success_counter++; + else + { + std::cout << "-----------------/! \\---------------" << std::endl; + std::cout << "Failure!" << std::endl; + std::cout << "Expected zero phase in both ends!" << std::endl; + std::cout << "-----------------/! \\---------------" << std::endl; + } + + std::cout << "-----------------/! \\---------------" << std::endl; + std::cout << "Test finished!" << std::endl; + std::cout << "Success rate: " << success_counter << "/" << test_number << std::endl; + std::cout << "-----------------/! \\---------------" << std::endl; + } + } +} + +void Splitter_tb_run() +{ + // Apply SPECS resolution before creating any device + specsGlobalConfig.applyEngineResolution(); + + spx::oa_signal_type IN, OUT1, OUT2; + + Splitter uut("uut"); + uut.m_attenuation_dB = 3.0103; + uut.p_in(IN); + uut.p_out1(OUT1); + uut.p_out2(OUT2); + + Splitter_tb tb("tb"); + tb.IN(IN); + tb.OUT1(OUT1); + tb.OUT2(OUT2); + + // Open Trace file + std::string trace_filename = "traces/"; + trace_filename += "splitter_tb"; + specsGlobalConfig.trace_filename = trace_filename; + + // Apply SPECS options specific to the testbench + specsGlobalConfig.simulation_mode = OpticalOutputPortMode::EVENT_DRIVEN; + specsGlobalConfig.trace_all_optical_nets = 0; + + Probe probe_splitter_1("probe_splitter_1",specsGlobalConfig.default_trace_file); + probe_splitter_1.p_in(OUT1); + + Probe probe_splitter_2("probe_splitter_2",specsGlobalConfig.default_trace_file); + probe_splitter_2.p_in(OUT2); + + // Run SPECS pre-simulation code + specsGlobalConfig.prepareSimulation(); + + // Start simulation + sc_start(); + + std::cout << std::endl << std::endl; + std::cout << ".vcd trace file: " << specsGlobalConfig.trace_filename << std::endl; + + sc_close_vcd_trace_file(specsGlobalConfig.default_trace_file); +} diff --git a/src/tb/splitter_tb.h b/src/tb/splitter_tb.h new file mode 100644 index 0000000..68d2a8d --- /dev/null +++ b/src/tb/splitter_tb.h @@ -0,0 +1,29 @@ +#pragma once + +#include <optical_signal.h> +#include <splitter.h> +#include <systemc.h> +#include <probe.h> +#include <specs.h> + +SC_MODULE(Splitter_tb) +{ +public: + spx::oa_port_out_type IN; + spx::oa_port_in_type OUT1; + spx::oa_port_in_type OUT2; + + void run_1(); + void monitor(); + SC_CTOR(Splitter_tb) + { + SC_HAS_PROCESS(Splitter_tb); + + SC_THREAD(run_1); + + SC_THREAD(monitor); + sensitive << IN << OUT1 << OUT2; + } +}; + +void Splitter_tb_run(); diff --git a/src/tb/wg_tb.cpp b/src/tb/wg_tb.cpp new file mode 100644 index 0000000..7ccebf5 --- /dev/null +++ b/src/tb/wg_tb.cpp @@ -0,0 +1,143 @@ +#include <ctime> +#include <iomanip> +#include <tb/wg_tb.h> + +#include "general_utils.h" +#include "devices/generic_waveguide.h" +#include "specs.h" + +void wg_tb::run_1() +{ + IN->write(OpticalSignal(sqrt(1.0), 1550e-9)); + wait(100, SC_MS); + IN->write(OpticalSignal(0, 1550e-9)); + wait(100, SC_MS); + IN->write(OpticalSignal(sqrt(2.0), 1550e-9)); + wait(100, SC_MS); + IN->write(OpticalSignal(0, 1550e-9)); + wait(10, SC_PS); + IN->write(OpticalSignal(sqrt(3.0), 1550e-9)); + wait(100, SC_MS); + + while (true) { wait(); } +} + +void wg_tb::monitor() +{ + unsigned int event_counter = 0; + unsigned int success_counter = 0; + const unsigned int test_number = 3; + while(true) + { + wait(); + event_counter++; + std::cout << sc_time_stamp() << ":" << std::endl + << "\tIN: " << IN->read() << std::endl + << "\tOUT: " << OUT->read() << std::endl + << "\tCOUNT: " << event_counter << std::endl; + + if(event_counter == 2) + { + if (is_close(norm(OUT->read().m_field), 0.5, 1e-4)) + success_counter++; + else + { + std::cout << "-----------------/! \\---------------" << std::endl; + std::cout << "Failure!" << std::endl; + std::cout << "Expected 0.5W as output power!" << std::endl; + std::cout << "-----------------/! \\---------------" << std::endl; + } + } + if(event_counter == 6) + { + if (is_close(arg(OUT->read().m_field), -2.4322, 1e-4)) + success_counter++; + else + { + std::cout << "-----------------/! \\---------------" << std::endl; + std::cout << "Failure!" << std::endl; + std::cout << "Expected -2.4322 rad as output phase!" << std::endl; + std::cout << "-----------------/! \\---------------" << std::endl; + } + } + if(event_counter == 10) + { + if (is_close(norm(OUT->read().m_field), 1.5, 1e-4) && (is_close(arg(OUT->read().m_field), -2.4322, 1e-4))) + success_counter++; + else + { + std::cout << "-----------------/! \\---------------" << std::endl; + std::cout << "Failure!" << std::endl; + std::cout << "Expected 1.5W as output power and -2.4322 as output phase!" << std::endl; + std::cout << "-----------------/! \\---------------" << std::endl; + } + + std::cout << "-----------------/! \\---------------" << std::endl; + std::cout << "Test finished!" << std::endl; + std::cout << "Success rate: " << success_counter << "/" << test_number << std::endl; + std::cout << "-----------------/! \\---------------" << std::endl; + } + } + +} + +void wg_tb_run() +{ + // Apply SPECS resolution before creating any device + specsGlobalConfig.applyEngineResolution(); + + spx::oa_signal_type IN("sig_in"), OUT("sig_out"); + spx::oa_signal_type TERM_r, TERM_w; + + // Unidirectional variant + // Waveguide uut("uut", 1, 0, 1, 1); + // uut.m_attenuation_dB_cm = 3.0103; + // uut.p_in(IN); + // uut.p_out(OUT); + + // Bidirectional variant + WaveguideBi uut("uut", 1, 0, 1, 1); + uut.m_attenuation_dB_cm = 3.0103; + uut.p0_in(IN); + uut.p0_out(TERM_w); + uut.p1_in(TERM_r); + uut.p1_out(OUT); + + // GenericWaveguide uut("uut",3.0103*100,1,1,0.01); + // uut.ports_in[0]->bind(IN); + // uut.ports_in[1]->bind(TERM_r); + // uut.ports_out[0]->bind(TERM_w); + // uut.ports_out[1]->bind(OUT); + + // Connect testbench to uut + wg_tb tb("tb"); + tb.IN(IN); + tb.OUT(OUT); + + // Attach probes + Probe probe_in("in"); + probe_in.p_in(IN); + + Probe probe_out("out"); + probe_out.p_in(OUT); + + // Open Trace file + std::string trace_filename = "traces/"; + trace_filename += "waveguide_tb"; + specsGlobalConfig.trace_filename = trace_filename; + + // Apply SPECS options specific to the testbench + specsGlobalConfig.simulation_mode = OpticalOutputPortMode::EVENT_DRIVEN; + specsGlobalConfig.trace_all_optical_nets = 0; + + // Run SPECS pre-simulation code + specsGlobalConfig.prepareSimulation(); + + // Start simulation + sc_start(); + + std::cout << std::endl << std::endl; + std::cout << ".vcd trace file: " << specsGlobalConfig.trace_filename << std::endl; + + sc_close_vcd_trace_file(specsGlobalConfig.default_trace_file); +} diff --git a/src/tb/wg_tb.h b/src/tb/wg_tb.h new file mode 100644 index 0000000..5d0a84f --- /dev/null +++ b/src/tb/wg_tb.h @@ -0,0 +1,28 @@ +#pragma once + +#include <optical_signal.h> +#include <systemc.h> +#include <waveguide.h> +#include <probe.h> +#include <specs.h> + +SC_MODULE(wg_tb) +{ +public: + spx::oa_port_out_type IN; + spx::oa_port_in_type OUT; + + void run_1(); + void monitor(); + SC_CTOR(wg_tb) + { + SC_HAS_PROCESS(wg_tb); + + SC_THREAD(run_1); + + SC_THREAD(monitor); + sensitive << IN << OUT; + } +}; + +void wg_tb_run(); |
