#pragma once #include #include "infra/arbiter.h" #include "infra/pipetrace.h" #include "infra/port.h" #include "io/model.h" #include "isa/checker.h" #include "isa/isa.h" #include "memory/cache.h" #include "memory/dram.h" struct core; struct restart { infra::transaction tr; unsigned int new_pc; bool interrupt; unsigned int stores_sent = 0; }; struct fetch_bundle { infra::transaction tr; unsigned int gen; unsigned int pc; memory::line data; }; struct inst_bundle { infra::transaction tr; unsigned int gen; unsigned int pc; std::uint64_t icount; instruction_context inst; }; struct fetch_stage : public infra::sim { core &c; memory::inline_cache<8, 2> cache; unsigned int pc; bool didrestart = false; bool outstandingfill = false; fetch_stage(core &c); void clock(); }; struct decode_stage : public infra::sim { core &c; bool interrupt = false; unsigned int pc; std::uint64_t icount; unsigned int speculative_stores_sent = 0; decode_stage(core &c); void clock(); }; struct indir_stage : public infra::sim { core &c; unsigned int gen = 0; indir_stage(core &c); void clock(); }; struct exec_stage : public infra::sim { core &c; unsigned int cycles_since_progress = 0; unsigned int gen = 0; unsigned int stores_sent = 0; unsigned int acc; unsigned int link; unsigned int mq; unsigned int pc; std::array ctlregs; exec_stage(core &c); void clock(); }; struct core { iomodel &system; funcchecker checker; std::optional restarto; unsigned int gen = 0; std::uint64_t icount; memory::dram mem{0}; infra::port mem_commandp; infra::priority_arbiter mem_command_arb; infra::port fetch_mem_commandp; infra::port fetch_mem_responsep; infra::port fetch_bundlep; infra::port decode_mem_commandp; infra::port decode_mem_responsep; infra::port decode_to_exec_instp; infra::port indir_instp; infra::port indir_mem_load_commandp; infra::port indir_mem_store_commandp; infra::port indir_mem_responsep; infra::port indir_to_exec_instp; infra::port exec_mem_commandp; infra::port exec_mem_responsep; // Global counters (should be Gray code in FPGA implementation, only do == comparisons) unsigned int stores_done = 0; // Construction order is execution order within a cycle, so this list should be back-to-front (for zero-cycle restarts and store count propagation) exec_stage exec{*this}; indir_stage indir{*this}; decode_stage decode{*this}; fetch_stage fetch{*this}; core(iomodel &model) : system(model) , checker(model) , icount(checker.icount) { mem.commandp = &mem_commandp; mem_command_arb.outp = &mem_commandp; mem_command_arb.peerp[0] = &exec_mem_commandp; mem_command_arb.peerp[1] = &indir_mem_store_commandp; mem_command_arb.peerp[2] = &indir_mem_load_commandp; mem_command_arb.peerp[3] = &decode_mem_commandp; mem_command_arb.peerp[4] = &fetch_mem_commandp; } };