data/full_repos/permissive/422650017/verilog/rtl/elpis/datapath.v
1: b'%Error: data/full_repos/permissive/422650017/verilog/rtl/elpis/datapath.v:17: Cannot find include file: /project/openlane/user_proj_example/../../verilog/rtl/elpis/definitions.v\n    `include "/project/openlane/user_proj_example/../../verilog/rtl/elpis/definitions.v" \n             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n        ... Looked in:\n             data/full_repos/permissive/422650017/verilog/rtl/elpis,data/full_repos/permissive/422650017//project/openlane/user_proj_example/../../verilog/rtl/elpis/definitions.v\n             data/full_repos/permissive/422650017/verilog/rtl/elpis,data/full_repos/permissive/422650017//project/openlane/user_proj_example/../../verilog/rtl/elpis/definitions.v.v\n             data/full_repos/permissive/422650017/verilog/rtl/elpis,data/full_repos/permissive/422650017//project/openlane/user_proj_example/../../verilog/rtl/elpis/definitions.v.sv\n             /project/openlane/user_proj_example/../../verilog/rtl/elpis/definitions.v\n             /project/openlane/user_proj_example/../../verilog/rtl/elpis/definitions.v.v\n             /project/openlane/user_proj_example/../../verilog/rtl/elpis/definitions.v.sv\n             obj_dir//project/openlane/user_proj_example/../../verilog/rtl/elpis/definitions.v\n             obj_dir//project/openlane/user_proj_example/../../verilog/rtl/elpis/definitions.v.v\n             obj_dir//project/openlane/user_proj_example/../../verilog/rtl/elpis/definitions.v.sv\n%Error: data/full_repos/permissive/422650017/verilog/rtl/elpis/datapath.v:189: Define or directive not defined: \'`PC_INITIAL\'\n   pc <= `PC_INITIAL;\n         ^~~~~~~~~~~\n%Error: data/full_repos/permissive/422650017/verilog/rtl/elpis/datapath.v:189: syntax error, unexpected \';\', expecting TYPE-IDENTIFIER\n   pc <= `PC_INITIAL;\n                    ^\n%Error: data/full_repos/permissive/422650017/verilog/rtl/elpis/datapath.v:197: Define or directive not defined: \'`PC_EXCEPTIONS\'\n   pc <= `PC_EXCEPTIONS;\n         ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/422650017/verilog/rtl/elpis/datapath.v:197: syntax error, unexpected \';\', expecting TYPE-IDENTIFIER\n   pc <= `PC_EXCEPTIONS;\n                       ^\n%Error: data/full_repos/permissive/422650017/verilog/rtl/elpis/datapath.v:225: Define or directive not defined: \'`EXC_ITLB_MISS\'\n wire[31:0] f_exc_code_in = (!hit_itlb && !privilege_mode) ? `EXC_ITLB_MISS : 0;\n                                                             ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/422650017/verilog/rtl/elpis/datapath.v:225: syntax error, unexpected \':\', expecting TYPE-IDENTIFIER\n wire[31:0] f_exc_code_in = (!hit_itlb && !privilege_mode) ? `EXC_ITLB_MISS : 0;\n                                                                            ^\n%Error: data/full_repos/permissive/422650017/verilog/rtl/elpis/datapath.v:287: Define or directive not defined: \'`MOV_REGULAR_TO_RM\'\n    .we(wb_is_mov == `MOV_REGULAR_TO_RM || wb_read_interactive_enable),\n                     ^~~~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/422650017/verilog/rtl/elpis/datapath.v:287: syntax error, unexpected ||, expecting TYPE-IDENTIFIER\n    .we(wb_is_mov == `MOV_REGULAR_TO_RM || wb_read_interactive_enable),\n                                        ^~\n%Error: data/full_repos/permissive/422650017/verilog/rtl/elpis/datapath.v:345: Define or directive not defined: \'`FUNCT3_BRANCH_NO\'\n assign ex_opX_pre = (ex_branch_code != `FUNCT3_BRANCH_NO) ? ex_pc : ex_reg_opX;\n                                        ^~~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/422650017/verilog/rtl/elpis/datapath.v:345: syntax error, unexpected \')\', expecting TYPE-IDENTIFIER\n assign ex_opX_pre = (ex_branch_code != `FUNCT3_BRANCH_NO) ? ex_pc : ex_reg_opX;\n                                                         ^\n%Error: data/full_repos/permissive/422650017/verilog/rtl/elpis/datapath.v:434: Define or directive not defined: \'`EXC_DTLB_MISS\'\n wire[31:0] mem_exc_code_in = ( (mem_mem_to_reg || mem_wrd || (mem_mem_we && !hit_dtlb)) && !hit_dtlb && !privilege_mode) ? `EXC_DTLB_MISS : 0;\n                                                                                                                            ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/422650017/verilog/rtl/elpis/datapath.v:434: syntax error, unexpected \':\', expecting TYPE-IDENTIFIER\n wire[31:0] mem_exc_code_in = ( (mem_mem_to_reg || mem_wrd || (mem_mem_we && !hit_dtlb)) && !hit_dtlb && !privilege_mode) ? `EXC_DTLB_MISS : 0;\n                                                                                                                                           ^\n%Error: data/full_repos/permissive/422650017/verilog/rtl/elpis/datapath.v:436: Define or directive not defined: \'`FUNCT7_IO_READ_SW\'\n assign read_interactive_req = (mem_io_code == `FUNCT7_IO_READ_SW);\n                                               ^~~~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/422650017/verilog/rtl/elpis/datapath.v:436: syntax error, unexpected \')\', expecting TYPE-IDENTIFIER\n assign read_interactive_req = (mem_io_code == `FUNCT7_IO_READ_SW);\n                                                                 ^\n%Error: data/full_repos/permissive/422650017/verilog/rtl/elpis/datapath.v:460: Define or directive not defined: \'`FUNCT7_IO_PRINT_HEX\'\n assign print_hex_enable = (wb_io_code == `FUNCT7_IO_PRINT_HEX);\n                                          ^~~~~~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/422650017/verilog/rtl/elpis/datapath.v:460: syntax error, unexpected \')\', expecting TYPE-IDENTIFIER\n assign print_hex_enable = (wb_io_code == `FUNCT7_IO_PRINT_HEX);\n                                                              ^\n%Error: Exiting due to 17 error(s)\n'
module datapath #(parameter CORE_ID=0) (
	input clk,
	input reset,
	input[31:0] mem_data_rd_f,
	input[31:0] mem_data_rd_m,
	input hit_icache,
	input hit_dcache,
	input hit_itlb,
	input hit_dtlb,
	input[31:0] read_interactive_value,
	input is_read_interactive_enabled,
	output[31:0] mem_addr_f,
	output[31:0] mem_addr_m,
	output[31:0] mem_data_wr,
	output mem_wrd,
	output dcache_re,
	output mem_isbyte,
	output reset_mem_req,
	output privilege_mode,
	output is_tlbwrite,
	output[31:0] current_address_rm2,
	output[19:0] mem_physical_tlb_addr_out,
	output[31:0] exception_type,
	output[31:0] print_output,
	output print_hex_enable,
	output read_interactive_req,
	input is_print_done
);
	wire stall_icache, stall_dcache;
	wire[31:0] global_rm0;

	wire[31:0] branch_or_jump_address_wire;
	wire is_branch_or_jump_taken_wire, is_iret_wire;
	reg is_iret_ff;	

	reg flush;
	reg boot;

	wire[3:0] id_alu_op;
	wire id_reg_we;
	wire[4:0] id_reg_src1_addr, id_reg_src2_addr, id_reg_dest_addr;
	wire[31:0] id_reg_a_content, id_reg_b_content;
	wire[2:0] id_branch_code;
	wire id_is_a_jump;
	wire id_regb_immed;
	wire[31:0] id_immediate;
	wire id_mem_to_reg;
	wire id_mem_we;
	wire id_stall;
	wire id_is_byte, id_is_ecall, id_is_iret;
	wire[1:0] id_is_mov;
	wire[6:0] id_io_code;
	wire[31:0] id_is_illegal;
	wire[31:0] id_reg_rm, id_rm2, id_rm1, id_rm0, id_current_rm1, id_current_rm2, id_current_rm4;
	wire id_is_tlbwrite, is_iret, id_hit_itlb;
	wire[31:0] id_reg_dest_value;
	
	wire[31:0] ex_reg_a, ex_reg_b;
	wire[31:0] ex_res_alu, ex_res_mul;
	wire[31:0] ex_reg_opX, ex_reg_opY;
	wire[3:0] ex_alu_op;
	wire[4:0] ex_reg_addr_dest;
	wire ex_z;
	wire ex_reg_write_enable;
	wire ex_mem_to_reg;
	wire ex_mem_we;
	wire ex_is_branch_taken;
	wire[31:0] ex_immed;
 	wire ex_regb_immed;
	wire[31:0] ex_pc;
	wire[2:0] ex_branch_code;
	wire ex_is_a_jump;
	wire[4:0] ex_reg_a_addr, ex_reg_b_addr;
	wire[31:0] ex_exc_code;
	wire[31:0] ex_rm0, ex_rm1, ex_rm2;
	wire ex_is_byte, ex_pend_haz, ex_is_ecall;
	wire[1:0] ex_is_mov;
	wire[6:0] ex_io_code;
	wire[31:0] ex_reg_rm, ex_reg_rm3, ex_current_rm1, ex_current_rm2, ex_current_rm4, ex_physical_tlb_addr;
	wire ex_is_tlbwrite, ex_is_iret, ex_hit_itlb;

	wire mem_z;
	wire[31:0] mem_branch_or_jump_address;
	wire mem_is_branch_taken;
	wire mem_is_a_jump;
	wire mem_is_branch_or_jump_taken;
	wire mem_reg_write_enable;
	wire[4:0] mem_reg_addr_dest;
	wire[31:0] mem_reg_data;
	wire mem_mem_to_reg;
	wire mem_mem_we;
	wire[31:0] mem_reg_b;
	wire[31:0] mem_rm0, mem_rm1, mem_rm2, mem_rm3, mem_current_rm1, mem_current_rm2, mem_current_rm4, mem_physical_tlb_addr;
	wire mem_is_byte;
	wire[1:0] mem_is_mov;
	wire[4:0] mem_reg_b_addr;
	wire[6:0] mem_io_code;
	wire mem_is_iret, mem_hit_itlb, mem_is_ecall, mem_is_tlbwrite;
	wire[31:0] mem_pc;
	wire mem_stall_read_sw;

	wire[31:0] wb_alu_res;
	wire[31:0] wb_current_rm4;
	wire[4:0] wb_addr_d, wb_addr_d_from_mem, wb_addr_d_from_m5;
	wire wb_reg_write_enable, wb_reg_write_enable_from_mem, wb_reg_write_enable_from_m5;
	wire[31:0] wb_data_to_reg, wb_data_to_reg_from_mem, wb_data_to_reg_from_m5;
	wire[31:0] wb_rm0, wb_rm1, wb_rm2;
	wire wb_is_iret, wb_hit_dtlb, wb_hit_itlb;
	wire[1:0] wb_is_mov;
	wire[6:0] wb_io_code;
	wire[31:0] wb_pc;
	wire[31:0] wb_read_interactive_value;
	wire wb_read_interactive_enable;
	

	wire was_stall_dcache, sb_data_to_cache_aux_in, sb_data_to_cache_aux_out, sb_hit_aux_in,sb_hit_aux_out, sb_is_byte_aux_out, sb_is_byte_aux_in;
	wire[31:0] sb_addr_out_aux_in, sb_data_out_aux_in, sb_addr_out_aux_out, sb_data_out_aux_out;
	wire sb_hit, sb_full, sb_empty, sb_is_byte, sb_continue_drain_out, sb_data_to_cache_out, sb_drain;

	wire wb_or_hf_reg_write_enable;
	wire[31:0] wb_or_hf_data_to_reg;
	wire[4:0] wb_or_hf_addr_to_reg; 
	wire[31:0] wb_or_hf_rm0, wb_or_hf_rm1, wb_or_hf_rm2;
	wire id_is_flush, ex_is_flush, mem_is_flush, wb_is_flush;

	wire is_exception, is_exception_reached;
	reg is_exception_pending;
	reg f_PSW;
	wire id_PSW, ex_PSW, mem_PSW, wb_PSW;
	wire stall_print;
	


	reg[31:0] cycleNumber;
	initial cycleNumber = 0;
	always@(posedge clk) cycleNumber = cycleNumber + 1'b1;



	
	reg[31:0] pc;
	wire[31:0] pc_next, id_pc, id_inst, f_pc;
	
	always@(reset or is_branch_or_jump_taken_wire)
	begin
		if(reset) begin
			flush <= 1'b1;
		end
		else begin
			flush <= is_branch_or_jump_taken_wire;
		end
	end
	
	assign stall_icache = !hit_icache;
	

	assign is_exception = is_exception_pending || is_exception_reached;
	assign reset_mem_req = is_exception;
	
	reg[31:0] branch_or_jump_address_ff;
	reg is_branch_or_jump_taken_ff;
	reg was_a_stall;
	
	assign branch_or_jump_address_wire = was_a_stall ? ((is_iret_wire) ? global_rm0 : branch_or_jump_address_ff) : ((is_iret_wire) ? global_rm0 : mem_branch_or_jump_address);
	assign is_branch_or_jump_taken_wire = was_a_stall ? is_branch_or_jump_taken_ff : mem_is_branch_or_jump_taken;
	assign is_iret_wire = was_a_stall ? is_iret_ff : mem_is_iret;

	always@(posedge clk) begin
		if (reset) begin
			pc <= `PC_INITIAL;
			was_a_stall <= 1'b0;
			is_branch_or_jump_taken_ff <= 1'b0;
			f_PSW <= 1'b1;
			is_iret_ff <= 1'b0;
			boot <= 1'b1;
			is_exception_pending <= 1'b0;
		end else if (is_exception | boot) begin
			pc <= `PC_EXCEPTIONS;
			f_PSW <= 1'b1;
			boot <= 1'b0;
			is_exception_pending <= 1'b0;
		end else if ((id_stall | stall_icache | stall_dcache | mem_stall_read_sw | stall_print)) begin
			pc <= pc;
			was_a_stall <= 1'b1;
			f_PSW <= f_PSW;
			if(mem_is_branch_or_jump_taken) begin
				branch_or_jump_address_ff <= is_branch_or_jump_taken_ff ? branch_or_jump_address_ff : mem_branch_or_jump_address;
				is_branch_or_jump_taken_ff <= mem_is_branch_or_jump_taken;
				is_iret_ff <= mem_is_iret;
			end
			is_exception_pending <= is_exception_pending || is_exception_reached;
		end else begin
			pc <= (is_branch_or_jump_taken_wire == 1'b0) ? pc_next : branch_or_jump_address_wire;
			was_a_stall <= 1'b0;
			is_branch_or_jump_taken_ff <= 1'b0;
			f_PSW <= is_iret_wire ? 1'b0 : f_PSW;
			is_iret_ff <= 1'b0;
			is_exception_pending <= is_exception_pending || is_exception_reached;
		end
	end

	assign pc_next = pc+4;
	assign mem_addr_f = pc;
	wire[31:0] f_inst = mem_data_rd_f;
	
	wire[31:0] f_exc_code_in = (!hit_itlb && !privilege_mode) ? `EXC_ITLB_MISS : 0;

	IF_ID IF_ID(.clk(clk), .stall_icache(stall_icache), .stall(id_stall | stall_dcache | (sb_drain && sb_full) | stall_print), .flush(flush | is_exception | mem_stall_read_sw), .pc_in(pc), 
	.psw_in(f_PSW), .is_flush_in(1'b0),
	.inst_in(f_inst), .is_hit_itlb_in(hit_itlb), .exc_code_in(f_exc_code_in), .pc_out(id_pc), .inst_out(id_inst), .is_hit_itlb_out(id_hit_itlb), .rm2_out(id_rm2), 
	.psw_out(id_PSW), .rm1_out(id_rm1), .rm0_out(id_rm0), .is_flush_out(id_is_flush));



	
	assign id_reg_src1_addr = id_inst[19:15];
	assign id_reg_src2_addr = id_inst[24:20];

	hazardDetectionUnit hazardDetectionUnit(
		.ex_reg_dest_addr_in(ex_reg_addr_dest),
		.ex_mem_read_in(ex_mem_to_reg),
		.id_reg_a_addr_in(id_reg_src1_addr),
		.id_reg_b_addr_in(id_reg_src2_addr),
		.stall_out(id_stall)
	);

	controlunit controlunit(
		.rst(reset),
		.ir(id_inst),
		.op_alu(id_alu_op),
		.wrd_reg(id_reg_we),
		.addr_d(id_reg_dest_addr),
		.rb_immed(id_regb_immed),
		.imm(id_immediate),
		.mem_to_reg(id_mem_to_reg),
		.wrd_mem(id_mem_we),
		.branch_code(id_branch_code),
		.is_a_jump(id_is_a_jump),
		.is_byte(id_is_byte),
		.is_mov(id_is_mov),
		.is_illegal(id_is_illegal),
		.is_tlbwrite(id_is_tlbwrite),
		.is_iret(id_is_iret),
		.is_ecall(id_is_ecall),
		.io_code(id_io_code)
	);

	regfile regfile(
		.clk(clk),
		.reset(reset),
		.wrd(wb_or_hf_reg_write_enable),
		.d(wb_or_hf_data_to_reg),
		.addr_a(id_reg_src1_addr),
		.addr_b(id_reg_src2_addr),
		.addr_d(wb_or_hf_addr_to_reg),
		.a(id_reg_a_content),
		.b(id_reg_b_content)
	);
	
	specialreg specialreg(
	   .clk(clk),
	   .reset(reset),
	   .in_rm0(wb_or_hf_rm0),
	   .in_rm1(wb_or_hf_rm1),
	   .in_rm2(is_branch_or_jump_taken_wire ? 0 : wb_or_hf_rm2),
	   .in_other_rm(wb_data_to_reg),
	   .sel(id_reg_src2_addr[2:0]),
	   .we(wb_is_mov == `MOV_REGULAR_TO_RM || wb_read_interactive_enable),
	   .out_rm0(global_rm0),
	   .out_rm1(id_current_rm1),
	   .out_rm2(id_current_rm2),
	   .out_rm(id_reg_rm),
	   .out_rm4(id_current_rm4)
	);

 	
	ID_EX ID_EX(.clk(clk), .flush(flush | is_exception), .haz(id_stall | ex_pend_haz), .stall(stall_dcache | (sb_drain && sb_full) | mem_stall_read_sw | stall_print), .reg_a_in(id_reg_a_content), .reg_b_in(id_reg_b_content), .alu_op_in(id_alu_op), 
		.reg_addr_dest_in(id_reg_dest_addr), .reg_write_enable_in(id_reg_we), .rb_imm_in(id_regb_immed), .immed_in(id_immediate),  .io_code_in(id_io_code),
		.mem_to_reg_in(id_mem_to_reg), .mem_we_in(id_mem_we), .pc_in(id_pc), .branch_code_in(id_branch_code), .is_flush_in(1'b0),
		.is_a_jump_in(id_is_a_jump), .reg_a_addr_in(id_reg_src1_addr), .reg_b_addr_in(id_reg_src2_addr), .is_byte_in(id_is_byte),
		.is_mov_in(id_is_mov), .reg_rm_in(id_reg_rm), .psw_in(id_PSW), .exc_code_in(id_is_illegal), .is_tlbwrite_in(id_is_tlbwrite), .is_iret_in(id_is_iret), .is_ecall_in(id_is_ecall),
		.is_hit_itlb_in(id_hit_itlb), .rm2_in(id_rm2), .rm1_in(id_rm1), .rm0_in(id_rm0), .stored_rm1_in(id_current_rm1), .stored_rm2_in(id_current_rm2), .stored_rm4_in(id_current_rm4), .fw_reg_a_in(ex_reg_opX), .fw_reg_b_in(ex_reg_opY),
		.reg_a_out(ex_reg_a), .reg_b_out(ex_reg_b), .alu_op_out(ex_alu_op), .reg_addr_dest_out(ex_reg_addr_dest), .reg_write_enable_out(ex_reg_write_enable), 
		.rb_imm_out(ex_regb_immed), .immed_out(ex_immed), .mem_to_reg_out(ex_mem_to_reg), .mem_we_out(ex_mem_we), .pc_out(ex_pc), .io_code_out(ex_io_code),
		.branch_code_out(ex_branch_code), .is_a_jump_out(ex_is_a_jump), .reg_a_addr_out(ex_reg_a_addr), .reg_b_addr_out(ex_reg_b_addr), .is_flush_out(ex_is_flush),
		.is_byte_out(ex_is_byte), .is_mov_out(ex_is_mov), .reg_rm_out(ex_reg_rm), .psw_out(ex_PSW), .stored_rm1_out(ex_current_rm1), .stored_rm2_out(ex_current_rm2), .stored_rm4_out(ex_current_rm4),
		.is_tlbwrite_out(ex_is_tlbwrite), .is_iret_out(ex_is_iret), .is_hit_itlb_out(ex_hit_itlb), .rm2_out(ex_rm2), .rm1_out(ex_rm1), .rm0_out(ex_rm0), .pending_haz(ex_pend_haz), .is_ecall_out(ex_is_ecall));
		 
		 


	wire[1:0] ex_forward_x, ex_forward_y;
	
	forwardingunit forwardingunit(
		.ex_reg_a_in(ex_reg_a_addr),
		.ex_reg_b_in(ex_reg_b_addr),
		.mem_reg_d_in(mem_reg_addr_dest),
		.wb_reg_d_in(wb_addr_d),
		.mem_reg_we_in(mem_reg_write_enable),
		.wb_reg_we_in(wb_reg_write_enable),
		.forward_x(ex_forward_x),
		.forward_y(ex_forward_y)
	);
	
	mux3_1 muxOpX(ex_forward_x, ex_reg_a, wb_data_to_reg, mem_reg_data, ex_reg_opX);
	mux3_1 muxOpY(ex_forward_y, ex_reg_b, wb_data_to_reg, mem_reg_data, ex_reg_opY);
	

	wire[31:0] ex_reg_b_fw;
	
	wire[1:0] forwarding_reg_b;
	
	forwardingunit_st forwardingunit_st(
		.mem_we(ex_mem_we),
		.ex_reg_b_in(ex_reg_b_addr),
		.mem_reg_b_in(mem_reg_b_addr),
		.forwarding_y(ex_forward_y),
		.forwarding_regb(forwarding_reg_b)
	);
	
	mux3_1 muxRegB(forwarding_reg_b, ex_reg_b, ex_reg_opY, mem_reg_b, ex_reg_b_fw);
	
	wire[31:0] ex_opX, ex_opX_pre;
	wire[31:0] ex_opY, ex_opY_pre;
	
	assign ex_opX_pre = (ex_branch_code != `FUNCT3_BRANCH_NO) ? ex_pc : ex_reg_opX;
	assign ex_opY_pre = (ex_regb_immed > 0) ? ex_immed : ex_reg_opY;
	
	assign ex_opX = (ex_is_mov == 2'b01) ? ex_reg_rm : ( (ex_is_mov == 2'b10) ? 32'b0 : ex_opX_pre);
	assign ex_opY = (ex_is_mov == 2'b01) ? 32'b0 : ex_opY_pre;
	
	branchComparer branchComparer(
		.branch_code_in(ex_branch_code), 
		.reg_a_content_in(ex_reg_opX), 
		.reg_b_content_in(ex_reg_opY), 
		.is_branch_taken_out(ex_is_branch_taken)
	);
	
	alu alu(
		.x(ex_opX),
		.y(ex_opY),
		.op(ex_alu_op),
		.w(ex_res_alu),
		.z(ex_z),
		.exception_code(ex_exc_code)
	);
	
	TLBAddressAdder #(.CORE_ID(CORE_ID)) TLBAddressAdder(
		.address_in(ex_current_rm1),
		.exception_code_in(ex_current_rm2),
		.address_out(ex_physical_tlb_addr)
	);


	EX_MEM EX_MEM(.clk(clk), .flush(flush | is_exception), .stall(stall_dcache | (sb_drain && sb_full) | mem_stall_read_sw | stall_print), .reg_write_enable_in(ex_reg_write_enable), .reg_dest_in(ex_reg_addr_dest),
	.reg_data_in(ex_res_alu), .mem_to_reg_in(ex_mem_to_reg), .mem_we_in(ex_mem_we), .reg_b_in(ex_reg_b_fw), .pc_in(ex_pc), .is_ecall_in(ex_is_ecall), .io_code_in(ex_io_code),
	.pc_candidate_address_in(ex_res_alu), .z_in(ex_z), .is_branch_taken_in(ex_is_branch_taken), .is_a_jump_in(ex_is_a_jump), .physical_tlb_addr_in(ex_physical_tlb_addr), .is_mov_in(ex_is_mov),
	.exc_code_in(ex_exc_code), .rm0_in(ex_rm0), .rm1_in(ex_rm1), .rm2_in(ex_rm2), .psw_in(ex_PSW), .is_byte_in(ex_is_byte), .stored_rm1_in(ex_current_rm1), .stored_rm2_in(ex_current_rm2), .stored_rm4_in(ex_current_rm4),
	.reg_b_addr_in(ex_reg_b_addr), .sb_addr_out_in(sb_addr_out_aux_in), .sb_is_byte_in(sb_is_byte_aux_in), .sb_data_out_in(sb_data_out_aux_in), .sb_data_to_cache_in(sb_data_to_cache_aux_in), 
	.sb_hit_in(sb_hit_aux_in), .was_stall_dcache_in(stall_dcache), .is_tlbwrite_in(ex_is_tlbwrite), .is_iret_in(ex_is_iret), .is_hit_itlb_in(ex_hit_itlb), .is_flush_in(1'b0),
	.reg_write_enable_out(mem_reg_write_enable), .reg_dest_out(mem_reg_addr_dest), .reg_data_out(mem_reg_data), .mem_to_reg_out(mem_mem_to_reg), .is_mov_out(mem_is_mov),
	.mem_we_out(mem_mem_we), .reg_b_out(mem_reg_b), .pc_candidate_address_out(mem_branch_or_jump_address), .z_out(mem_z), .is_branch_taken_out(mem_is_branch_taken), .is_flush_out(mem_is_flush), .io_code_out(mem_io_code),
	.is_a_jump_out(mem_is_a_jump), .rm0_out(mem_rm0), .rm1_out(mem_rm1), .rm2_out(mem_rm2), .psw_out(mem_PSW), .is_byte_out(mem_is_byte), .sb_is_byte_out(sb_is_byte_aux_out), .stored_rm1_out(mem_current_rm1), .stored_rm2_out(mem_current_rm2),
	.reg_b_addr_out(mem_reg_b_addr), .sb_addr_out_out(sb_addr_out_aux_out), .sb_data_out_out(sb_data_out_aux_out), .sb_data_to_cache_out(sb_data_to_cache_aux_out), .physical_tlb_addr_out(mem_physical_tlb_addr), .stored_rm4_out(mem_current_rm4),
	.sb_hit_out(sb_hit_aux_out), .was_stall_dcache_out(was_stall_dcache), .is_tlbwrite_out(mem_is_tlbwrite), .is_iret_out(mem_is_iret), .is_hit_itlb_out(mem_hit_itlb), .pc_out(mem_pc),.is_ecall_out(mem_is_ecall));
	
	assign mem_is_branch_or_jump_taken = mem_is_branch_taken | mem_is_a_jump;
	assign stall_dcache =  (!hit_dcache & mem_mem_to_reg & sb_hit_aux_in) ? 1'b0 : !hit_dcache;



	assign dcache_re = mem_mem_to_reg;
	
	wire[31:0] sb_addr_out, sb_data_out;
	assign sb_drain = sb_continue_drain_out;
	
	assign privilege_mode = f_PSW;
	assign is_tlbwrite = mem_is_tlbwrite;
	assign exception_type = mem_current_rm2;
	assign current_address_rm2 = mem_current_rm1;
	assign mem_physical_tlb_addr_out = mem_physical_tlb_addr[19:0];
	
	storebuffer storebuffer(
		.clk(clk),
	 	.reset(reset),
	 	.addr_in(mem_reg_data),
	 	.data_in(mem_reg_b),
	 	.is_byte(mem_is_byte),
	 	.sb_we(mem_mem_we && !flush),
	 	.sb_re(mem_mem_to_reg),
	 	.stall_dcache(stall_dcache),
		.hit_dtlb(hit_dtlb),
	 	.sb_hit(sb_hit_aux_in),
	 	.full_out(sb_full),
	 	.empty_out(sb_empty),
	 	.addr_out(sb_addr_out_aux_in),
	 	.data_out(sb_data_out_aux_in),
	 	.is_byte_out(sb_is_byte_aux_in),
	 	.drain_out(sb_continue_drain_out),
	 	.is_data_to_cache(sb_data_to_cache_aux_in)
	);

	assign sb_addr_out = (was_stall_dcache) ? sb_addr_out_aux_out : sb_addr_out_aux_in;
	assign sb_data_out = (was_stall_dcache) ? sb_data_out_aux_out : sb_data_out_aux_in;
	assign sb_data_to_cache_out = (was_stall_dcache) ? sb_data_to_cache_aux_out : sb_data_to_cache_aux_in;
	assign sb_hit = (was_stall_dcache) ? sb_hit_aux_out : sb_hit_aux_in;
	assign sb_is_byte = (was_stall_dcache) ? sb_is_byte_aux_out : sb_is_byte_aux_in;
	
	assign mem_addr_m = (sb_data_to_cache_out) ? sb_addr_out : mem_reg_data;
	assign mem_data_wr = sb_data_out;
	assign mem_isbyte = mem_mem_to_reg ? mem_is_byte : sb_is_byte;
	assign mem_wrd = sb_data_to_cache_out;
	wire[31:0] data_from_mem = (sb_hit) ? sb_data_out : mem_data_rd_m;

	wire[31:0] mem_exc_code_in = ( (mem_mem_to_reg || mem_wrd || (mem_mem_we && !hit_dtlb)) && !hit_dtlb && !privilege_mode) ? `EXC_DTLB_MISS : 0;

	assign read_interactive_req = (mem_io_code == `FUNCT7_IO_READ_SW);
	assign mem_stall_read_sw = read_interactive_req && !is_read_interactive_enabled;




	wire[31:0] wb_mem_data;
	wire wb_mem_to_reg;
	wire mem_flush = (stall_dcache && hit_dtlb) | is_exception;

	MEM_WB MEM_WB(.clk(clk), .flush(mem_flush), .stall(stall_print), .reg_dest_in(mem_reg_addr_dest), .reg_write_enable_in(mem_reg_write_enable), .reg_data_alu_in(mem_reg_data),  .io_code_in(mem_io_code), .read_interactive_value_in(read_interactive_value), .is_read_interactive_enabled_in(is_read_interactive_enabled),
	.mem_data_in(data_from_mem), .mem_to_reg_in(mem_mem_to_reg), .rm0_in(mem_rm0), .rm1_in(mem_rm1), .rm2_in(mem_rm2), .psw_in(mem_PSW), .is_iret_in(mem_is_iret), .is_ecall_in(mem_is_ecall), .stored_rm4_in(mem_current_rm4),
	.is_hit_dtlb_in(hit_dtlb), .is_hit_itlb_in(mem_hit_itlb), .exc_code_in(mem_exc_code_in), .mem_addr_in(mem_addr_m), .pc_in(mem_pc), .is_flush_in(1'b0), .is_mov_in(mem_is_mov),
	.reg_dest_out(wb_addr_d_from_mem), .reg_data_alu_out(wb_alu_res), .reg_write_enable_out(wb_reg_write_enable_from_mem), .mem_data_out(wb_mem_data), .io_code_out(wb_io_code),
	.mem_to_reg_out(wb_mem_to_reg), .rm0_out(wb_rm0), .rm1_out(wb_rm1), .rm2_out(wb_rm2), .is_iret_out(wb_is_iret), .is_hit_dtlb_out(wb_hit_dtlb),  .is_mov_out(wb_is_mov),
	.is_hit_itlb_out(wb_hit_itlb), .pc_out(wb_pc), .is_flush_out(wb_is_flush), .stored_rm4_out(wb_current_rm4), .read_interactive_value_out(wb_read_interactive_value), .is_read_interactive_enabled_out(wb_read_interactive_enable));

	assign wb_data_to_reg_from_mem = (wb_mem_to_reg > 0) ? wb_mem_data : wb_alu_res;

	assign wb_reg_write_enable = (wb_read_interactive_enable  ? 1'b0 : wb_reg_write_enable_from_mem );
	assign wb_data_to_reg = (wb_read_interactive_enable ? wb_read_interactive_value : wb_data_to_reg_from_mem);
	assign wb_addr_d = wb_addr_d_from_mem;

	assign print_output = wb_current_rm4;
	assign print_hex_enable = (wb_io_code == `FUNCT7_IO_PRINT_HEX);
	assign stall_print = !is_print_done;	

	assign wb_or_hf_addr_to_reg = wb_addr_d;
	assign wb_or_hf_data_to_reg = wb_data_to_reg;
	assign wb_or_hf_reg_write_enable = wb_reg_write_enable;

	assign is_exception_reached = (wb_rm2 > 0 && !is_branch_or_jump_taken_wire);

	assign wb_or_hf_rm0 = wb_rm0;
	assign wb_or_hf_rm1 = wb_rm1;
	assign wb_or_hf_rm2 = wb_rm2;

endmodule
module datapath #(parameter CORE_ID=0) (
	input clk,
	input reset,
	input[31:0] mem_data_rd_f,
	input[31:0] mem_data_rd_m,
	input hit_icache,
	input hit_dcache,
	input hit_itlb,
	input hit_dtlb,
	input[31:0] read_interactive_value,
	input is_read_interactive_enabled,
	output[31:0] mem_addr_f,
	output[31:0] mem_addr_m,
	output[31:0] mem_data_wr,
	output mem_wrd,
	output dcache_re,
	output mem_isbyte,
	output reset_mem_req,
	output privilege_mode,
	output is_tlbwrite,
	output[31:0] current_address_rm2,
	output[19:0] mem_physical_tlb_addr_out,
	output[31:0] exception_type,
	output[31:0] print_output,
	output print_hex_enable,
	output read_interactive_req,
	input is_print_done
);

	wire stall_icache, stall_dcache;
	wire[31:0] global_rm0;

	wire[31:0] branch_or_jump_address_wire;
	wire is_branch_or_jump_taken_wire, is_iret_wire;
	reg is_iret_ff;	

	reg flush;
	reg boot;

	wire[3:0] id_alu_op;
	wire id_reg_we;
	wire[4:0] id_reg_src1_addr, id_reg_src2_addr, id_reg_dest_addr;
	wire[31:0] id_reg_a_content, id_reg_b_content;
	wire[2:0] id_branch_code;
	wire id_is_a_jump;
	wire id_regb_immed;
	wire[31:0] id_immediate;
	wire id_mem_to_reg;
	wire id_mem_we;
	wire id_stall;
	wire id_is_byte, id_is_ecall, id_is_iret;
	wire[1:0] id_is_mov;
	wire[6:0] id_io_code;
	wire[31:0] id_is_illegal;
	wire[31:0] id_reg_rm, id_rm2, id_rm1, id_rm0, id_current_rm1, id_current_rm2, id_current_rm4;
	wire id_is_tlbwrite, is_iret, id_hit_itlb;
	wire[31:0] id_reg_dest_value;
	
	wire[31:0] ex_reg_a, ex_reg_b;
	wire[31:0] ex_res_alu, ex_res_mul;
	wire[31:0] ex_reg_opX, ex_reg_opY;
	wire[3:0] ex_alu_op;
	wire[4:0] ex_reg_addr_dest;
	wire ex_z;
	wire ex_reg_write_enable;
	wire ex_mem_to_reg;
	wire ex_mem_we;
	wire ex_is_branch_taken;
	wire[31:0] ex_immed;
 	wire ex_regb_immed;
	wire[31:0] ex_pc;
	wire[2:0] ex_branch_code;
	wire ex_is_a_jump;
	wire[4:0] ex_reg_a_addr, ex_reg_b_addr;
	wire[31:0] ex_exc_code;
	wire[31:0] ex_rm0, ex_rm1, ex_rm2;
	wire ex_is_byte, ex_pend_haz, ex_is_ecall;
	wire[1:0] ex_is_mov;
	wire[6:0] ex_io_code;
	wire[31:0] ex_reg_rm, ex_reg_rm3, ex_current_rm1, ex_current_rm2, ex_current_rm4, ex_physical_tlb_addr;
	wire ex_is_tlbwrite, ex_is_iret, ex_hit_itlb;

	wire mem_z;
	wire[31:0] mem_branch_or_jump_address;
	wire mem_is_branch_taken;
	wire mem_is_a_jump;
	wire mem_is_branch_or_jump_taken;
	wire mem_reg_write_enable;
	wire[4:0] mem_reg_addr_dest;
	wire[31:0] mem_reg_data;
	wire mem_mem_to_reg;
	wire mem_mem_we;
	wire[31:0] mem_reg_b;
	wire[31:0] mem_rm0, mem_rm1, mem_rm2, mem_rm3, mem_current_rm1, mem_current_rm2, mem_current_rm4, mem_physical_tlb_addr;
	wire mem_is_byte;
	wire[1:0] mem_is_mov;
	wire[4:0] mem_reg_b_addr;
	wire[6:0] mem_io_code;
	wire mem_is_iret, mem_hit_itlb, mem_is_ecall, mem_is_tlbwrite;
	wire[31:0] mem_pc;
	wire mem_stall_read_sw;

	wire[31:0] wb_alu_res;
	wire[31:0] wb_current_rm4;
	wire[4:0] wb_addr_d, wb_addr_d_from_mem, wb_addr_d_from_m5;
	wire wb_reg_write_enable, wb_reg_write_enable_from_mem, wb_reg_write_enable_from_m5;
	wire[31:0] wb_data_to_reg, wb_data_to_reg_from_mem, wb_data_to_reg_from_m5;
	wire[31:0] wb_rm0, wb_rm1, wb_rm2;
	wire wb_is_iret, wb_hit_dtlb, wb_hit_itlb;
	wire[1:0] wb_is_mov;
	wire[6:0] wb_io_code;
	wire[31:0] wb_pc;
	wire[31:0] wb_read_interactive_value;
	wire wb_read_interactive_enable;
	

	wire was_stall_dcache, sb_data_to_cache_aux_in, sb_data_to_cache_aux_out, sb_hit_aux_in,sb_hit_aux_out, sb_is_byte_aux_out, sb_is_byte_aux_in;
	wire[31:0] sb_addr_out_aux_in, sb_data_out_aux_in, sb_addr_out_aux_out, sb_data_out_aux_out;
	wire sb_hit, sb_full, sb_empty, sb_is_byte, sb_continue_drain_out, sb_data_to_cache_out, sb_drain;

	wire wb_or_hf_reg_write_enable;
	wire[31:0] wb_or_hf_data_to_reg;
	wire[4:0] wb_or_hf_addr_to_reg; 
	wire[31:0] wb_or_hf_rm0, wb_or_hf_rm1, wb_or_hf_rm2;
	wire id_is_flush, ex_is_flush, mem_is_flush, wb_is_flush;

	wire is_exception, is_exception_reached;
	reg is_exception_pending;
	reg f_PSW;
	wire id_PSW, ex_PSW, mem_PSW, wb_PSW;
	wire stall_print;
	


	reg[31:0] cycleNumber;
	initial cycleNumber = 0;
	always@(posedge clk) cycleNumber = cycleNumber + 1'b1;



	
	reg[31:0] pc;
	wire[31:0] pc_next, id_pc, id_inst, f_pc;
	
	always@(reset or is_branch_or_jump_taken_wire)
	begin
		if(reset) begin
			flush <= 1'b1;
		end
		else begin
			flush <= is_branch_or_jump_taken_wire;
		end
	end
	
	assign stall_icache = !hit_icache;
	

	assign is_exception = is_exception_pending || is_exception_reached;
	assign reset_mem_req = is_exception;
	
	reg[31:0] branch_or_jump_address_ff;
	reg is_branch_or_jump_taken_ff;
	reg was_a_stall;
	
	assign branch_or_jump_address_wire = was_a_stall ? ((is_iret_wire) ? global_rm0 : branch_or_jump_address_ff) : ((is_iret_wire) ? global_rm0 : mem_branch_or_jump_address);
	assign is_branch_or_jump_taken_wire = was_a_stall ? is_branch_or_jump_taken_ff : mem_is_branch_or_jump_taken;
	assign is_iret_wire = was_a_stall ? is_iret_ff : mem_is_iret;

	always@(posedge clk) begin
		if (reset) begin
			pc <= `PC_INITIAL;
			was_a_stall <= 1'b0;
			is_branch_or_jump_taken_ff <= 1'b0;
			f_PSW <= 1'b1;
			is_iret_ff <= 1'b0;
			boot <= 1'b1;
			is_exception_pending <= 1'b0;
		end else if (is_exception | boot) begin
			pc <= `PC_EXCEPTIONS;
			f_PSW <= 1'b1;
			boot <= 1'b0;
			is_exception_pending <= 1'b0;
		end else if ((id_stall | stall_icache | stall_dcache | mem_stall_read_sw | stall_print)) begin
			pc <= pc;
			was_a_stall <= 1'b1;
			f_PSW <= f_PSW;
			if(mem_is_branch_or_jump_taken) begin
				branch_or_jump_address_ff <= is_branch_or_jump_taken_ff ? branch_or_jump_address_ff : mem_branch_or_jump_address;
				is_branch_or_jump_taken_ff <= mem_is_branch_or_jump_taken;
				is_iret_ff <= mem_is_iret;
			end
			is_exception_pending <= is_exception_pending || is_exception_reached;
		end else begin
			pc <= (is_branch_or_jump_taken_wire == 1'b0) ? pc_next : branch_or_jump_address_wire;
			was_a_stall <= 1'b0;
			is_branch_or_jump_taken_ff <= 1'b0;
			f_PSW <= is_iret_wire ? 1'b0 : f_PSW;
			is_iret_ff <= 1'b0;
			is_exception_pending <= is_exception_pending || is_exception_reached;
		end
	end

	assign pc_next = pc+4;
	assign mem_addr_f = pc;
	wire[31:0] f_inst = mem_data_rd_f;
	
	wire[31:0] f_exc_code_in = (!hit_itlb && !privilege_mode) ? `EXC_ITLB_MISS : 0;

	IF_ID IF_ID(.clk(clk), .stall_icache(stall_icache), .stall(id_stall | stall_dcache | (sb_drain && sb_full) | stall_print), .flush(flush | is_exception | mem_stall_read_sw), .pc_in(pc), 
	.psw_in(f_PSW), .is_flush_in(1'b0),
	.inst_in(f_inst), .is_hit_itlb_in(hit_itlb), .exc_code_in(f_exc_code_in), .pc_out(id_pc), .inst_out(id_inst), .is_hit_itlb_out(id_hit_itlb), .rm2_out(id_rm2), 
	.psw_out(id_PSW), .rm1_out(id_rm1), .rm0_out(id_rm0), .is_flush_out(id_is_flush));



	
	assign id_reg_src1_addr = id_inst[19:15];
	assign id_reg_src2_addr = id_inst[24:20];

	hazardDetectionUnit hazardDetectionUnit(
		.ex_reg_dest_addr_in(ex_reg_addr_dest),
		.ex_mem_read_in(ex_mem_to_reg),
		.id_reg_a_addr_in(id_reg_src1_addr),
		.id_reg_b_addr_in(id_reg_src2_addr),
		.stall_out(id_stall)
	);

	controlunit controlunit(
		.rst(reset),
		.ir(id_inst),
		.op_alu(id_alu_op),
		.wrd_reg(id_reg_we),
		.addr_d(id_reg_dest_addr),
		.rb_immed(id_regb_immed),
		.imm(id_immediate),
		.mem_to_reg(id_mem_to_reg),
		.wrd_mem(id_mem_we),
		.branch_code(id_branch_code),
		.is_a_jump(id_is_a_jump),
		.is_byte(id_is_byte),
		.is_mov(id_is_mov),
		.is_illegal(id_is_illegal),
		.is_tlbwrite(id_is_tlbwrite),
		.is_iret(id_is_iret),
		.is_ecall(id_is_ecall),
		.io_code(id_io_code)
	);

	regfile regfile(
		.clk(clk),
		.reset(reset),
		.wrd(wb_or_hf_reg_write_enable),
		.d(wb_or_hf_data_to_reg),
		.addr_a(id_reg_src1_addr),
		.addr_b(id_reg_src2_addr),
		.addr_d(wb_or_hf_addr_to_reg),
		.a(id_reg_a_content),
		.b(id_reg_b_content)
	);
	
	specialreg specialreg(
	   .clk(clk),
	   .reset(reset),
	   .in_rm0(wb_or_hf_rm0),
	   .in_rm1(wb_or_hf_rm1),
	   .in_rm2(is_branch_or_jump_taken_wire ? 0 : wb_or_hf_rm2),
	   .in_other_rm(wb_data_to_reg),
	   .sel(id_reg_src2_addr[2:0]),
	   .we(wb_is_mov == `MOV_REGULAR_TO_RM || wb_read_interactive_enable),
	   .out_rm0(global_rm0),
	   .out_rm1(id_current_rm1),
	   .out_rm2(id_current_rm2),
	   .out_rm(id_reg_rm),
	   .out_rm4(id_current_rm4)
	);

 	
	ID_EX ID_EX(.clk(clk), .flush(flush | is_exception), .haz(id_stall | ex_pend_haz), .stall(stall_dcache | (sb_drain && sb_full) | mem_stall_read_sw | stall_print), .reg_a_in(id_reg_a_content), .reg_b_in(id_reg_b_content), .alu_op_in(id_alu_op), 
		.reg_addr_dest_in(id_reg_dest_addr), .reg_write_enable_in(id_reg_we), .rb_imm_in(id_regb_immed), .immed_in(id_immediate),  .io_code_in(id_io_code),
		.mem_to_reg_in(id_mem_to_reg), .mem_we_in(id_mem_we), .pc_in(id_pc), .branch_code_in(id_branch_code), .is_flush_in(1'b0),
		.is_a_jump_in(id_is_a_jump), .reg_a_addr_in(id_reg_src1_addr), .reg_b_addr_in(id_reg_src2_addr), .is_byte_in(id_is_byte),
		.is_mov_in(id_is_mov), .reg_rm_in(id_reg_rm), .psw_in(id_PSW), .exc_code_in(id_is_illegal), .is_tlbwrite_in(id_is_tlbwrite), .is_iret_in(id_is_iret), .is_ecall_in(id_is_ecall),
		.is_hit_itlb_in(id_hit_itlb), .rm2_in(id_rm2), .rm1_in(id_rm1), .rm0_in(id_rm0), .stored_rm1_in(id_current_rm1), .stored_rm2_in(id_current_rm2), .stored_rm4_in(id_current_rm4), .fw_reg_a_in(ex_reg_opX), .fw_reg_b_in(ex_reg_opY),
		.reg_a_out(ex_reg_a), .reg_b_out(ex_reg_b), .alu_op_out(ex_alu_op), .reg_addr_dest_out(ex_reg_addr_dest), .reg_write_enable_out(ex_reg_write_enable), 
		.rb_imm_out(ex_regb_immed), .immed_out(ex_immed), .mem_to_reg_out(ex_mem_to_reg), .mem_we_out(ex_mem_we), .pc_out(ex_pc), .io_code_out(ex_io_code),
		.branch_code_out(ex_branch_code), .is_a_jump_out(ex_is_a_jump), .reg_a_addr_out(ex_reg_a_addr), .reg_b_addr_out(ex_reg_b_addr), .is_flush_out(ex_is_flush),
		.is_byte_out(ex_is_byte), .is_mov_out(ex_is_mov), .reg_rm_out(ex_reg_rm), .psw_out(ex_PSW), .stored_rm1_out(ex_current_rm1), .stored_rm2_out(ex_current_rm2), .stored_rm4_out(ex_current_rm4),
		.is_tlbwrite_out(ex_is_tlbwrite), .is_iret_out(ex_is_iret), .is_hit_itlb_out(ex_hit_itlb), .rm2_out(ex_rm2), .rm1_out(ex_rm1), .rm0_out(ex_rm0), .pending_haz(ex_pend_haz), .is_ecall_out(ex_is_ecall));
		 
		 


	wire[1:0] ex_forward_x, ex_forward_y;
	
	forwardingunit forwardingunit(
		.ex_reg_a_in(ex_reg_a_addr),
		.ex_reg_b_in(ex_reg_b_addr),
		.mem_reg_d_in(mem_reg_addr_dest),
		.wb_reg_d_in(wb_addr_d),
		.mem_reg_we_in(mem_reg_write_enable),
		.wb_reg_we_in(wb_reg_write_enable),
		.forward_x(ex_forward_x),
		.forward_y(ex_forward_y)
	);
	
	mux3_1 muxOpX(ex_forward_x, ex_reg_a, wb_data_to_reg, mem_reg_data, ex_reg_opX);
	mux3_1 muxOpY(ex_forward_y, ex_reg_b, wb_data_to_reg, mem_reg_data, ex_reg_opY);
	

	wire[31:0] ex_reg_b_fw;
	
	wire[1:0] forwarding_reg_b;
	
	forwardingunit_st forwardingunit_st(
		.mem_we(ex_mem_we),
		.ex_reg_b_in(ex_reg_b_addr),
		.mem_reg_b_in(mem_reg_b_addr),
		.forwarding_y(ex_forward_y),
		.forwarding_regb(forwarding_reg_b)
	);
	
	mux3_1 muxRegB(forwarding_reg_b, ex_reg_b, ex_reg_opY, mem_reg_b, ex_reg_b_fw);
	
	wire[31:0] ex_opX, ex_opX_pre;
	wire[31:0] ex_opY, ex_opY_pre;
	
	assign ex_opX_pre = (ex_branch_code != `FUNCT3_BRANCH_NO) ? ex_pc : ex_reg_opX;
	assign ex_opY_pre = (ex_regb_immed > 0) ? ex_immed : ex_reg_opY;
	
	assign ex_opX = (ex_is_mov == 2'b01) ? ex_reg_rm : ( (ex_is_mov == 2'b10) ? 32'b0 : ex_opX_pre);
	assign ex_opY = (ex_is_mov == 2'b01) ? 32'b0 : ex_opY_pre;
	
	branchComparer branchComparer(
		.branch_code_in(ex_branch_code), 
		.reg_a_content_in(ex_reg_opX), 
		.reg_b_content_in(ex_reg_opY), 
		.is_branch_taken_out(ex_is_branch_taken)
	);
	
	alu alu(
		.x(ex_opX),
		.y(ex_opY),
		.op(ex_alu_op),
		.w(ex_res_alu),
		.z(ex_z),
		.exception_code(ex_exc_code)
	);
	
	TLBAddressAdder #(.CORE_ID(CORE_ID)) TLBAddressAdder(
		.address_in(ex_current_rm1),
		.exception_code_in(ex_current_rm2),
		.address_out(ex_physical_tlb_addr)
	);


	EX_MEM EX_MEM(.clk(clk), .flush(flush | is_exception), .stall(stall_dcache | (sb_drain && sb_full) | mem_stall_read_sw | stall_print), .reg_write_enable_in(ex_reg_write_enable), .reg_dest_in(ex_reg_addr_dest),
	.reg_data_in(ex_res_alu), .mem_to_reg_in(ex_mem_to_reg), .mem_we_in(ex_mem_we), .reg_b_in(ex_reg_b_fw), .pc_in(ex_pc), .is_ecall_in(ex_is_ecall), .io_code_in(ex_io_code),
	.pc_candidate_address_in(ex_res_alu), .z_in(ex_z), .is_branch_taken_in(ex_is_branch_taken), .is_a_jump_in(ex_is_a_jump), .physical_tlb_addr_in(ex_physical_tlb_addr), .is_mov_in(ex_is_mov),
	.exc_code_in(ex_exc_code), .rm0_in(ex_rm0), .rm1_in(ex_rm1), .rm2_in(ex_rm2), .psw_in(ex_PSW), .is_byte_in(ex_is_byte), .stored_rm1_in(ex_current_rm1), .stored_rm2_in(ex_current_rm2), .stored_rm4_in(ex_current_rm4),
	.reg_b_addr_in(ex_reg_b_addr), .sb_addr_out_in(sb_addr_out_aux_in), .sb_is_byte_in(sb_is_byte_aux_in), .sb_data_out_in(sb_data_out_aux_in), .sb_data_to_cache_in(sb_data_to_cache_aux_in), 
	.sb_hit_in(sb_hit_aux_in), .was_stall_dcache_in(stall_dcache), .is_tlbwrite_in(ex_is_tlbwrite), .is_iret_in(ex_is_iret), .is_hit_itlb_in(ex_hit_itlb), .is_flush_in(1'b0),
	.reg_write_enable_out(mem_reg_write_enable), .reg_dest_out(mem_reg_addr_dest), .reg_data_out(mem_reg_data), .mem_to_reg_out(mem_mem_to_reg), .is_mov_out(mem_is_mov),
	.mem_we_out(mem_mem_we), .reg_b_out(mem_reg_b), .pc_candidate_address_out(mem_branch_or_jump_address), .z_out(mem_z), .is_branch_taken_out(mem_is_branch_taken), .is_flush_out(mem_is_flush), .io_code_out(mem_io_code),
	.is_a_jump_out(mem_is_a_jump), .rm0_out(mem_rm0), .rm1_out(mem_rm1), .rm2_out(mem_rm2), .psw_out(mem_PSW), .is_byte_out(mem_is_byte), .sb_is_byte_out(sb_is_byte_aux_out), .stored_rm1_out(mem_current_rm1), .stored_rm2_out(mem_current_rm2),
	.reg_b_addr_out(mem_reg_b_addr), .sb_addr_out_out(sb_addr_out_aux_out), .sb_data_out_out(sb_data_out_aux_out), .sb_data_to_cache_out(sb_data_to_cache_aux_out), .physical_tlb_addr_out(mem_physical_tlb_addr), .stored_rm4_out(mem_current_rm4),
	.sb_hit_out(sb_hit_aux_out), .was_stall_dcache_out(was_stall_dcache), .is_tlbwrite_out(mem_is_tlbwrite), .is_iret_out(mem_is_iret), .is_hit_itlb_out(mem_hit_itlb), .pc_out(mem_pc),.is_ecall_out(mem_is_ecall));
	
	assign mem_is_branch_or_jump_taken = mem_is_branch_taken | mem_is_a_jump;
	assign stall_dcache =  (!hit_dcache & mem_mem_to_reg & sb_hit_aux_in) ? 1'b0 : !hit_dcache;



	assign dcache_re = mem_mem_to_reg;
	
	wire[31:0] sb_addr_out, sb_data_out;
	assign sb_drain = sb_continue_drain_out;
	
	assign privilege_mode = f_PSW;
	assign is_tlbwrite = mem_is_tlbwrite;
	assign exception_type = mem_current_rm2;
	assign current_address_rm2 = mem_current_rm1;
	assign mem_physical_tlb_addr_out = mem_physical_tlb_addr[19:0];
	
	storebuffer storebuffer(
		.clk(clk),
	 	.reset(reset),
	 	.addr_in(mem_reg_data),
	 	.data_in(mem_reg_b),
	 	.is_byte(mem_is_byte),
	 	.sb_we(mem_mem_we && !flush),
	 	.sb_re(mem_mem_to_reg),
	 	.stall_dcache(stall_dcache),
		.hit_dtlb(hit_dtlb),
	 	.sb_hit(sb_hit_aux_in),
	 	.full_out(sb_full),
	 	.empty_out(sb_empty),
	 	.addr_out(sb_addr_out_aux_in),
	 	.data_out(sb_data_out_aux_in),
	 	.is_byte_out(sb_is_byte_aux_in),
	 	.drain_out(sb_continue_drain_out),
	 	.is_data_to_cache(sb_data_to_cache_aux_in)
	);

	assign sb_addr_out = (was_stall_dcache) ? sb_addr_out_aux_out : sb_addr_out_aux_in;
	assign sb_data_out = (was_stall_dcache) ? sb_data_out_aux_out : sb_data_out_aux_in;
	assign sb_data_to_cache_out = (was_stall_dcache) ? sb_data_to_cache_aux_out : sb_data_to_cache_aux_in;
	assign sb_hit = (was_stall_dcache) ? sb_hit_aux_out : sb_hit_aux_in;
	assign sb_is_byte = (was_stall_dcache) ? sb_is_byte_aux_out : sb_is_byte_aux_in;
	
	assign mem_addr_m = (sb_data_to_cache_out) ? sb_addr_out : mem_reg_data;
	assign mem_data_wr = sb_data_out;
	assign mem_isbyte = mem_mem_to_reg ? mem_is_byte : sb_is_byte;
	assign mem_wrd = sb_data_to_cache_out;
	wire[31:0] data_from_mem = (sb_hit) ? sb_data_out : mem_data_rd_m;

	wire[31:0] mem_exc_code_in = ( (mem_mem_to_reg || mem_wrd || (mem_mem_we && !hit_dtlb)) && !hit_dtlb && !privilege_mode) ? `EXC_DTLB_MISS : 0;

	assign read_interactive_req = (mem_io_code == `FUNCT7_IO_READ_SW);
	assign mem_stall_read_sw = read_interactive_req && !is_read_interactive_enabled;




	wire[31:0] wb_mem_data;
	wire wb_mem_to_reg;
	wire mem_flush = (stall_dcache && hit_dtlb) | is_exception;

	MEM_WB MEM_WB(.clk(clk), .flush(mem_flush), .stall(stall_print), .reg_dest_in(mem_reg_addr_dest), .reg_write_enable_in(mem_reg_write_enable), .reg_data_alu_in(mem_reg_data),  .io_code_in(mem_io_code), .read_interactive_value_in(read_interactive_value), .is_read_interactive_enabled_in(is_read_interactive_enabled),
	.mem_data_in(data_from_mem), .mem_to_reg_in(mem_mem_to_reg), .rm0_in(mem_rm0), .rm1_in(mem_rm1), .rm2_in(mem_rm2), .psw_in(mem_PSW), .is_iret_in(mem_is_iret), .is_ecall_in(mem_is_ecall), .stored_rm4_in(mem_current_rm4),
	.is_hit_dtlb_in(hit_dtlb), .is_hit_itlb_in(mem_hit_itlb), .exc_code_in(mem_exc_code_in), .mem_addr_in(mem_addr_m), .pc_in(mem_pc), .is_flush_in(1'b0), .is_mov_in(mem_is_mov),
	.reg_dest_out(wb_addr_d_from_mem), .reg_data_alu_out(wb_alu_res), .reg_write_enable_out(wb_reg_write_enable_from_mem), .mem_data_out(wb_mem_data), .io_code_out(wb_io_code),
	.mem_to_reg_out(wb_mem_to_reg), .rm0_out(wb_rm0), .rm1_out(wb_rm1), .rm2_out(wb_rm2), .is_iret_out(wb_is_iret), .is_hit_dtlb_out(wb_hit_dtlb),  .is_mov_out(wb_is_mov),
	.is_hit_itlb_out(wb_hit_itlb), .pc_out(wb_pc), .is_flush_out(wb_is_flush), .stored_rm4_out(wb_current_rm4), .read_interactive_value_out(wb_read_interactive_value), .is_read_interactive_enabled_out(wb_read_interactive_enable));

	assign wb_data_to_reg_from_mem = (wb_mem_to_reg > 0) ? wb_mem_data : wb_alu_res;

	assign wb_reg_write_enable = (wb_read_interactive_enable  ? 1'b0 : wb_reg_write_enable_from_mem );
	assign wb_data_to_reg = (wb_read_interactive_enable ? wb_read_interactive_value : wb_data_to_reg_from_mem);
	assign wb_addr_d = wb_addr_d_from_mem;

	assign print_output = wb_current_rm4;
	assign print_hex_enable = (wb_io_code == `FUNCT7_IO_PRINT_HEX);
	assign stall_print = !is_print_done;	

	assign wb_or_hf_addr_to_reg = wb_addr_d;
	assign wb_or_hf_data_to_reg = wb_data_to_reg;
	assign wb_or_hf_reg_write_enable = wb_reg_write_enable;

	assign is_exception_reached = (wb_rm2 > 0 && !is_branch_or_jump_taken_wire);

	assign wb_or_hf_rm0 = wb_rm0;
	assign wb_or_hf_rm1 = wb_rm1;
	assign wb_or_hf_rm2 = wb_rm2;

endmodule