diff --git a/.gitmodules b/.gitmodules index ac88f432..48c52fb0 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "ihp13/pdk"] path = ihp13/pdk url = https://github.com/IHP-GmbH/IHP-Open-PDK +[submodule "circumspect"] + path = circumspect + url = https://github.com/schilkp/circumspect.git diff --git a/Bender.yml b/Bender.yml index fe9fc5d6..d6a50d07 100644 --- a/Bender.yml +++ b/Bender.yml @@ -61,6 +61,15 @@ sources: files: - yosys/out/croc_chip_yosys_debug.v + - target: cspect + defines: + CSPECT: ~ + include_dirs: + - circumspect/include + files: + - circumspect/include/cspect_pkg.sv + - rtl/test/croc_cspect.sv + - target: any(simulation, verilator) files: - rtl/test/tb_croc_pkg.sv diff --git a/Makefile b/Makefile index 212311f2..40d19756 100644 --- a/Makefile +++ b/Makefile @@ -13,6 +13,7 @@ YOSYS ?= yosys OPENROAD ?= openroad KLAYOUT ?= klayout VSIM ?= vsim +CARGO ?= cargo # Directories # directory of the path to the last called Makefile (this one) @@ -62,6 +63,12 @@ sw: $(SW_HEX) ################## # RTL Simulation # ################## +# CircumSpect DPI library +CSPECT_LIB := $(PROJ_DIR)/circumspect/target/release/libcspect.a + +$(CSPECT_LIB): circumspect/Cargo.toml + cd circumspect; $(CARGO) build --release --lib + # Questasim/Modelsim/vsim VLOG_ARGS = -svinputport=compat VSIM_ARGS = -t 1ns -voptargs=+acc @@ -98,10 +105,10 @@ VERILATOR_ARGS += --x-assign fast --x-initial fast VERILATOR_CFLAGS += -O3 -march=native -mtune=native verilator/croc.f: Bender.lock Bender.yml - $(BENDER) script verilator -t rtl -t verilator -t cve2_include_tracer -DSYNTHESIS -DVERILATOR -DTRACE_EXECUTION > $@ + $(BENDER) script verilator -t rtl -t verilator -t cve2_include_tracer -t cspect -DSYNTHESIS -DVERILATOR -DTRACE_EXECUTION > $@ -verilator/obj_dir/Vtb_croc_soc: verilator/croc.f $(SW_HEX) - cd verilator; $(VERILATOR) $(VERILATOR_ARGS) -O3 --top tb_croc_soc -f croc.f +verilator/obj_dir/Vtb_croc_soc: verilator/croc.f $(CSPECT_LIB) $(SW_HEX) + cd verilator; $(VERILATOR) $(VERILATOR_ARGS) -O3 --top tb_croc_soc -f croc.f $(CSPECT_LIB) ## Simulate RTL using Verilator verilator: verilator/obj_dir/Vtb_croc_soc diff --git a/circumspect b/circumspect new file mode 160000 index 00000000..b4ca5482 --- /dev/null +++ b/circumspect @@ -0,0 +1 @@ +Subproject commit b4ca5482e7a1d22cd3bd85cdc39a957adcef1cbd diff --git a/rtl/test/croc_cspect.sv b/rtl/test/croc_cspect.sv new file mode 100644 index 00000000..9ad2c628 --- /dev/null +++ b/rtl/test/croc_cspect.sv @@ -0,0 +1,521 @@ +package croc_cspect_pkg; + + // From CVE2 controller's FSM state encoding + typedef enum logic [3:0] { + RESET, BOOT_SET, WAIT_SLEEP, SLEEP, FIRST_FETCH, DECODE, FLUSH, + IRQ_TAKEN, DBG_TAKEN_IF, DBG_TAKEN_ID + } cve2_ctrl_fsm_e; + + // Croc SoC's CircumSpect interface signals + // Collects all signals relevant for logging + typedef struct { + logic fetch_en; + logic cve2_dbg_mode; + cve2_pkg::priv_lvl_e cve2_priv_mode; + logic cve2_dbg_req; + logic cve2_exc_req; + cve2_ctrl_fsm_e cve2_ctrl_state; + cve2_pkg::exc_cause_e cve2_exc_cause; + logic [31:0] cve2_exc_instr; + logic [31:0] cve2_pc; + logic cve2_inst_req; + logic cve2_inst_gnt; + logic cve2_inst_valid; + logic [31:0] cve2_inst_addr; + logic [31:0] cve2_inst_data; + logic cve2_data_req; + logic cve2_data_gnt; + logic cve2_data_valid; + logic cve2_data_we; + logic [31:0] cve2_data_addr; + logic [31:0] cve2_data_rdata; + logic cve2_data_wdata; + logic cve2_irq_software; + logic cve2_irq_timer; + logic cve2_irq_external; + logic [15:0] cve2_irq_fast; + logic cve2_irq_nm; + logic [31:0][31:0] cve2_regs; + } croc_cspect_if_t; + + ////////////////////// + // Helper functions // + ////////////////////// + + // Convert priviledge level enum to string + function automatic string cve2_priv_lvl_to_string(cve2_pkg::priv_lvl_e priv_lvl); + case(priv_lvl) + cve2_pkg::PRIV_LVL_M: begin + return "M"; + end + cve2_pkg::PRIV_LVL_H: begin + return "H"; + end + cve2_pkg::PRIV_LVL_S: begin + return "S"; + end + cve2_pkg::PRIV_LVL_U: begin + return "U"; + end + default: begin + return "?"; + end + endcase + endfunction + + // Convert CVE2 exception cause to string + function automatic string cve2_exception_to_string(cve2_pkg::exc_cause_e cause); + case(cause) + cve2_pkg::EXC_CAUSE_INSN_ADDR_MISA: begin + return "Address misaligned"; + end + cve2_pkg::EXC_CAUSE_INSTR_ACCESS_FAULT: begin + return "Instruction fault"; + end + cve2_pkg::EXC_CAUSE_ILLEGAL_INSN: begin + return "Illegal instruction"; + end + cve2_pkg::EXC_CAUSE_BREAKPOINT: begin + return "Breakpoint"; + end + cve2_pkg::EXC_CAUSE_LOAD_ACCESS_FAULT: begin + return "Load fault"; + end + cve2_pkg::EXC_CAUSE_STORE_ACCESS_FAULT: begin + return "Store fault"; + end + cve2_pkg::EXC_CAUSE_ECALL_UMODE: begin + return "ECALL U-mode"; + end + cve2_pkg::EXC_CAUSE_ECALL_MMODE: begin + return "ECALL M-mode"; + end + default: begin + return $sformatf("Cause: 0x%X", cause); + end + endcase + endfunction + + // Convert CVE2 controller's state to string + function automatic string cve2_state_to_string(cve2_ctrl_fsm_e state); + case(state) + RESET: begin + return "Reset"; + end + BOOT_SET: begin + return "Boot set"; + end + WAIT_SLEEP: begin + return "Wait sleep"; + end + SLEEP: begin + return "Sleep"; + end + FIRST_FETCH: begin + return "First fetch"; + end + DECODE: begin + return "Decode"; + end + FLUSH: begin + return "Flush"; + end + IRQ_TAKEN: begin + return "Irq"; + end + DBG_TAKEN_IF: begin + return "Dbg taken IF"; + end + DBG_TAKEN_ID: begin + return "Dbg taken ID"; + end + default: begin + return "??"; + end + endcase + endfunction + +endpackage + +interface croc_cspect_if; + + event start_log; + + logic fetch_en; + logic cve2_dbg_mode; + cve2_pkg::priv_lvl_e cve2_priv_mode; + logic cve2_dbg_req; + logic cve2_exc_req; + croc_cspect_pkg::cve2_ctrl_fsm_e cve2_ctrl_state; + cve2_pkg::exc_cause_e cve2_exc_cause; + logic [31:0] cve2_exc_instr; + logic [31:0] cve2_pc; + logic cve2_inst_req; + logic cve2_inst_gnt; + logic cve2_inst_valid; + logic [31:0] cve2_inst_addr; + logic [31:0] cve2_inst_data; + logic cve2_data_req; + logic cve2_data_gnt; + logic cve2_data_valid; + logic cve2_data_we; + logic [31:0] cve2_data_addr; + logic [31:0] cve2_data_rdata; + logic cve2_data_wdata; + logic cve2_irq_software; + logic cve2_irq_timer; + logic cve2_irq_external; + logic [15:0] cve2_irq_fast; + logic cve2_irq_nm; + logic [31:0][31:0] cve2_regs; + +endinterface + +module edge_detector ( + input logic clk_i, + input logic rst_ni, + input logic d_i, + output logic re_o, + output logic fe_o +); + + logic d_prev; + + always_ff @(posedge clk_i or negedge rst_ni) begin + if (~rst_ni) begin + d_prev <= '0; + end else begin + d_prev <= d_i; + end + end + + assign re_o = ~d_prev & d_i; + assign fe_o = d_prev & ~d_i; + +endmodule + +module croc_cspect_logger + import cspect_pkg::*; + import croc_cspect_pkg::*; +( + input logic clk_i, + input logic rst_ni, + croc_cspect_if croc_if +); + + //////////////////////////////// + // Helper signals and modules // + //////////////////////////////// + + // Instruction / data request + typedef struct packed { + logic valid; + logic we; + uuid_t flow; + } req_in_flight_t; + + logic cve2_exception; + logic fetch_en_asserted; + logic fetch_en_deasserted; + logic cve2_timer_irq_asserted; + logic cve2_timer_irq_deasserted; + logic cve2_software_irq_asserted; + logic cve2_software_irq_deasserted; + logic cve2_external_irq_asserted; + logic cve2_external_irq_deasserted; + logic cve2_nmi_irq_asserted; + logic cve2_nmi_irq_deasserted; + logic [15:0] cve2_fast_irq_asserted; + logic [15:0] cve2_fast_irq_deasserted; + req_in_flight_t inst_req_in_flight_q; + req_in_flight_t data_req_in_flight_q; + + edge_detector i_exception_edge_detect ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .d_i ( croc_if.cve2_exc_req ), + .re_o ( cve2_exception ), + .fe_o () + ); + + edge_detector i_fetch_en_edge_detect ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .d_i ( croc_if.fetch_en ), + .re_o ( fetch_en_asserted ), + .fe_o ( fetch_en_deasserted ) + ); + + edge_detector i_timer_irq_edge_detect ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .d_i ( croc_if.cve2_irq_timer ), + .re_o ( cve2_timer_irq_asserted ), + .fe_o ( cve2_timer_irq_deasserted ) + ); + + edge_detector i_software_irq_edge_detect ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .d_i ( croc_if.cve2_irq_software ), + .re_o ( cve2_software_irq_asserted ), + .fe_o ( cve2_software_irq_deasserted ) + ); + + edge_detector i_external_irq_edge_detect ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .d_i ( croc_if.cve2_irq_external ), + .re_o ( cve2_external_irq_asserted ), + .fe_o ( cve2_external_irq_deasserted ) + ); + + edge_detector i_nm_irq_edge_detect ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .d_i ( croc_if.cve2_irq_nm ), + .re_o ( cve2_nm_irq_asserted ), + .fe_o ( cve2_nm_irq_deasserted ) + ); + + generate + for (genvar i = 0; i < 16; ++i) begin + edge_detector i_fast_irq_edge_detect ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .d_i ( croc_if.cve2_irq_fast[i] ), + .re_o ( cve2_fast_irq_asserted[i] ), + .fe_o ( cve2_fast_irq_deasserted[i] ) + ); + end + endgenerate + + /////////////////////////////// + // Logging scopes and tracks // + /////////////////////////////// + + ctx cspect_ctx; + track sim_track; + // CVE2 top scope + scope cve2_scope; + // CVE2 overview scope + scope cve2_overview_scope; + track cve2_mode_track; + track cve2_dbg_req_track; + track cve2_exception_track; + track cve2_fetch_en_track; + track cve2_state_track; + // CVE2 interrupts scope + scope cve2_interrupts_scope; + track cve2_timer_irq_track; + track cve2_software_irq_track; + track cve2_external_irq_track; + track cve2_nm_irq_track; + track cve2_fast_irq_tracks [16]; + // CVE2 IF stage scope + scope cve2_if_scope; + track cve2_instr_req_track; + track cve2_instr_rsp_track; + // CVE2 LSU scope + scope cve2_lsu_scope; + track cve2_data_req_track; + track cve2_data_rsp_track; + // CVE2 register file scope + scope cve2_registers_scope; + track cve2_regfile_tracks [32]; + + //////////////////////////////// + // CirscumSpect logging setup // + //////////////////////////////// + string filename = "croc.pftrace"; + + initial begin + + wait(croc_if.start_log.triggered); + + cspect_ctx = new(filename); + $display("@%t | [INFO] Started cspect trace @ %s", $time, filename); + + sim_track = cspect_ctx.new_track("simulation"); + sim_track.instant_evt("begin"); + + cve2_scope = cspect_ctx.new_track("CVE2", .child_ordering(cspect_pkg::Explicit)); + cve2_overview_scope = cve2_scope.new_track("Overview", .child_ordering(cspect_pkg::Explicit), .child_order_rank(1)); + cve2_interrupts_scope = cve2_scope.new_track("Interrupts", .child_ordering(cspect_pkg::Explicit), .child_order_rank(2)); + cve2_if_scope = cve2_scope.new_track("IF stage", .child_ordering(cspect_pkg::Explicit), .child_order_rank(3)); + cve2_lsu_scope = cve2_scope.new_track("LSU", .child_ordering(cspect_pkg::Explicit), .child_order_rank(4)); + cve2_registers_scope = cve2_scope.new_track("Register file", .child_ordering(cspect_pkg::Explicit), .child_order_rank(5)); + + cve2_mode_track = cve2_overview_scope.new_track("Priviledge mode"); + cve2_dbg_req_track = cve2_overview_scope.new_track("Debug reqests"); + cve2_exception_track = cve2_overview_scope.new_track("Exceptions"); + cve2_fetch_en_track = cve2_overview_scope.new_track("Fetch enable"); + cve2_state_track = cve2_overview_scope.new_track("Controller FSM state"); + + cve2_timer_irq_track = cve2_interrupts_scope.new_track("Timer interrupts"); + cve2_software_irq_track = cve2_interrupts_scope.new_track("Software interrupts"); + cve2_external_irq_track = cve2_interrupts_scope.new_track("External interrupts"); + cve2_nm_irq_track = cve2_interrupts_scope.new_track("Non-maskable interrupts (NMIs)"); + foreach (cve2_fast_irq_tracks[i]) begin + cve2_fast_irq_tracks[i] = cve2_interrupts_scope.new_track($sformatf("Fast interrupt %1d", i)); + end + + cve2_instr_req_track = cve2_if_scope.new_track("Instruction requests"); + cve2_instr_rsp_track = cve2_if_scope.new_track("Instruction responses"); + + cve2_data_req_track = cve2_lsu_scope.new_track("Data requests"); + cve2_data_rsp_track = cve2_lsu_scope.new_track("Data responses"); + + foreach (cve2_regfile_tracks[i]) begin + cve2_regfile_tracks[i] = cve2_registers_scope.new_track($sformatf("X%1d", i)); + end + + end + + final begin + sim_track.instant_evt("end"); + cspect_ctx.finish(); + end + + //////////////////////////////// + // CirscumSpect logging logic // + //////////////////////////////// + + always @(posedge clk_i) begin + + if (~rst_ni) begin + + inst_req_in_flight_q <= '0; + data_req_in_flight_q <= '0; + + end else begin + + automatic string msg; + automatic req_in_flight_t inst_req_in_flight_d; + automatic req_in_flight_t data_req_in_flight_d; + + // Helper variables initialization + inst_req_in_flight_d = inst_req_in_flight_q; + data_req_in_flight_d = data_req_in_flight_q; + + // Privilege mode + msg = croc_if.cve2_dbg_mode ? "D" : cve2_priv_lvl_to_string(croc_if.cve2_priv_mode); + cve2_mode_track.slice_set(msg, .compress(1)); + + // Debug requests + if (croc_if.cve2_dbg_req) cve2_dbg_req_track.instant_evt("Req"); + + // Exceptions + if (cve2_exception) begin + msg = $sformatf( + "cause: %s pc: $a2l:0x%0h insn: $da-rv64:0x%0h", + cve2_exception_to_string(croc_if.cve2_exc_cause), + croc_if.cve2_pc, + croc_if.cve2_exc_instr + ); + cve2_exception_track.instant_evt(msg); + end + + // Fetch enable + if (fetch_en_asserted) begin + cve2_fetch_en_track.slice_set("Enabled", .compress(1)); + end else if (fetch_en_deasserted) begin + cve2_fetch_en_track.slice_end(); + end + + // CVE2 state + msg = cve2_state_to_string(croc_if.cve2_ctrl_state); + cve2_state_track.slice_set(msg, .compress(1)); + + // CVE2 interrupts + if (cve2_timer_irq_asserted) begin + cve2_timer_irq_track.slice_set("Timer interrupt", .compress(1)); + end else if (cve2_timer_irq_deasserted) begin + cve2_timer_irq_track.slice_end(); + end + if (cve2_software_irq_asserted) begin + cve2_software_irq_track.slice_set("Software interrupt", .compress(1)); + end else if (cve2_software_irq_deasserted) begin + cve2_software_irq_track.slice_end(); + end + if (cve2_external_irq_asserted) begin + cve2_external_irq_track.slice_set("External interrupt", .compress(1)); + end else if (cve2_external_irq_deasserted) begin + cve2_external_irq_track.slice_end(); + end + if (cve2_nm_irq_asserted) begin + cve2_nm_irq_track.slice_set("NMI set", .compress(1)); + end else if (cve2_nm_irq_deasserted) begin + cve2_nm_irq_track.slice_end(); + end + foreach (cve2_fast_irq_tracks[i]) begin + if (cve2_fast_irq_asserted[i]) begin + cve2_fast_irq_tracks[i].slice_set($sformatf("Fast interrupt %d", i)); + end else if (cve2_fast_irq_deasserted[i]) begin + cve2_fast_irq_tracks[i].slice_end(); + end + end + + // CVE2 instruction response + if (croc_if.cve2_inst_valid) begin + if (~inst_req_in_flight_q.valid) $error("Instruction response without valid in-flight transaction"); + msg = $sformatf("Data: 0x%08X", croc_if.cve2_inst_data); + inst_req_in_flight_d.valid = 1'b0; + cve2_instr_rsp_track.slice_set(msg, .flows({inst_req_in_flight_q.flow})); + end else begin + cve2_instr_rsp_track.slice_end(); + end + + // CVW2 instruction request + if (croc_if.cve2_inst_req && croc_if.cve2_inst_gnt) begin + automatic uuid_t flow = cve2_if_scope.new_uuid(); + msg = $sformatf("PC: 0x%08X", croc_if.cve2_inst_addr); + if (inst_req_in_flight_d.valid) $error("Multiple instruction requests in-flight"); + cve2_instr_req_track.slice_set(msg, .flows({flow})); + inst_req_in_flight_d.valid = 1'b1; + inst_req_in_flight_d.flow = flow; + end else begin + cve2_instr_req_track.slice_end(); + end + + // CVE2 data response + if (croc_if.cve2_data_valid) begin + if (~data_req_in_flight_q.valid) $error("Data response without valid in-flight transaction"); + data_req_in_flight_d.valid = 1'b0; + if (data_req_in_flight_q.we) begin + cve2_data_rsp_track.slice_set("Write ACK", .flows({data_req_in_flight_q.flow})); + end else begin + msg = $sformatf("Rdata: 0x%08X", croc_if.cve2_data_rdata); + cve2_data_rsp_track.slice_set(msg, .flows({data_req_in_flight_q.flow})); + end + end else begin + cve2_data_rsp_track.slice_end(); + end + + // CVE2 data request + if (croc_if.cve2_data_req && croc_if.cve2_data_gnt) begin + automatic uuid_t flow = cve2_lsu_scope.new_uuid(); + msg = $sformatf("%s @0x%08X", croc_if.cve2_data_we ? "Write" : "Read", croc_if.cve2_data_addr); + if (data_req_in_flight_d.valid) $error("Multiple data requests in-flight"); + cve2_data_req_track.slice_set(msg, .flows({flow})); + data_req_in_flight_d.valid = 1'b1; + data_req_in_flight_d.we = croc_if.cve2_data_we; + data_req_in_flight_d.flow = flow; + end else begin + cve2_data_req_track.slice_end(); + end + + // CVE2 registers + for (int i = 0; i < 32; ++i) begin + cve2_regfile_tracks[i].slice_set($sformatf("0x%08X", croc_if.cve2_regs[i]), .compress(1)); + end + + // Helper variables update + inst_req_in_flight_q <= inst_req_in_flight_d; + data_req_in_flight_q <= data_req_in_flight_d; + + end + + end + +endmodule diff --git a/rtl/test/tb_croc_soc.sv b/rtl/test/tb_croc_soc.sv index a3559254..3109e9ba 100644 --- a/rtl/test/tb_croc_soc.sv +++ b/rtl/test/tb_croc_soc.sv @@ -7,6 +7,7 @@ // - Enrico Zelioli `define TRACE_WAVE +// `define CSPECT module tb_croc_soc #( parameter int unsigned GpioCount = 32 @@ -115,6 +116,52 @@ module tb_croc_soc #( .gpio_out_en_o ( gpio_out_en ) ); + `ifdef CSPECT + + croc_cspect_if croc_cspect_if(); + + `ifdef TRACE_EXECUTION + `define I_CVE2 i_croc_soc.i_croc.i_core_wrap.i_ibex.u_cve2_core + `else + `define I_CVE2 i_croc_soc.i_croc.i_core_wrap.i_ibex + `endif + + assign croc_cspect_if.fetch_en = fetch_en; + assign croc_cspect_if.cve2_dbg_mode = `I_CVE2.debug_mode; + assign croc_cspect_if.cve2_priv_mode = `I_CVE2.priv_mode_id; + assign croc_cspect_if.cve2_dbg_req = `I_CVE2.id_stage_i.controller_i.enter_debug_mode; + assign croc_cspect_if.cve2_exc_req = `I_CVE2.id_stage_i.controller_i.exc_req_q; + assign croc_cspect_if.cve2_ctrl_state = croc_cspect_pkg::cve2_ctrl_fsm_e'(`I_CVE2.id_stage_i.controller_i.ctrl_fsm_cs); + assign croc_cspect_if.cve2_exc_cause = `I_CVE2.exc_cause; + assign croc_cspect_if.cve2_exc_instr = `I_CVE2.instr_rdata_id; + assign croc_cspect_if.cve2_pc = `I_CVE2.pc_id; + assign croc_cspect_if.cve2_inst_req = `I_CVE2.instr_req_o; + assign croc_cspect_if.cve2_inst_gnt = `I_CVE2.instr_gnt_i; + assign croc_cspect_if.cve2_inst_valid = `I_CVE2.instr_rvalid_i; + assign croc_cspect_if.cve2_inst_addr = `I_CVE2.instr_addr_o; + assign croc_cspect_if.cve2_inst_data = `I_CVE2.instr_rdata_i; + assign croc_cspect_if.cve2_data_req = `I_CVE2.data_req_o; + assign croc_cspect_if.cve2_data_gnt = `I_CVE2.data_gnt_i; + assign croc_cspect_if.cve2_data_valid = `I_CVE2.data_rvalid_i; + assign croc_cspect_if.cve2_data_we = `I_CVE2.data_we_o; + assign croc_cspect_if.cve2_data_addr = `I_CVE2.data_addr_o; + assign croc_cspect_if.cve2_data_rdata = `I_CVE2.data_rdata_i; + assign croc_cspect_if.cve2_data_wdata = `I_CVE2.data_wdata_o; + assign croc_cspect_if.cve2_irq_software = `I_CVE2.irq_software_i; + assign croc_cspect_if.cve2_irq_timer = `I_CVE2.irq_timer_i; + assign croc_cspect_if.cve2_irq_external = `I_CVE2.irq_external_i; + assign croc_cspect_if.cve2_irq_fast = `I_CVE2.irq_fast_i; + assign croc_cspect_if.cve2_irq_nm = `I_CVE2.irq_nm_i; + assign croc_cspect_if.cve2_regs = `I_CVE2.register_file_i.rf_reg; + + croc_cspect_logger i_croc_cspect_logger ( + .clk_i ( sys_clk ), + .rst_ni ( rst_n ), + .croc_if ( croc_cspect_if ) + ); + + `endif // CSPECT + ///////////////// // Testbench // ///////////////// @@ -124,6 +171,11 @@ module tb_croc_soc #( initial begin $timeformat(-9, 0, "ns", 12); // 1: scale (ns=-9), 2: decimals, 3: suffix, 4: print-field width + // Start CircumSpect logging + `ifdef CSPECT + ->croc_cspect_if.start_log; + `endif + fetch_en = 1'b0; // wait for reset