data/full_repos/permissive/153690221/dropbox/baddam_bourquin_ethakota_finalproject/Source/DataCache.v
 line:20: before: "="
1: b'%Warning-WIDTH: data/full_repos/permissive/153690221/dropbox/baddam_bourquin_ethakota_finalproject/Source/DataCache.v:421: Operator ASSIGN expects 3 bits on the Assign RHS, but Assign RHS\'s SUB generates 32 or 4 bits.\n                                                                                                                         : ... In instance DATA_CACHE\n     DataLine[DC_TagBits+DC_LRUBits-1:DC_TagBits] = 8-1;\n                                                  ^\n                ... Use "/* verilator lint_off WIDTH */" and lint_on around source to disable this message.\n%Warning-WIDTH: data/full_repos/permissive/153690221/dropbox/baddam_bourquin_ethakota_finalproject/Source/DataCache.v:175: Operator ASSIGN expects 32 bits on the Assign RHS, but Assign RHS\'s FUNCREF \'UpdateData_LRU\' generates 1 bits.\n                                                                                                                         : ... In instance DATA_CACHE\n   temp = UpdateData_LRU(DC_LRU, Index); \n        ^\n%Warning-WIDTH: data/full_repos/permissive/153690221/dropbox/baddam_bourquin_ethakota_finalproject/Source/DataCache.v:272: Operator ASSIGN expects 32 bits on the Assign RHS, but Assign RHS\'s FUNCREF \'UpdateData_LRU\' generates 1 bits.\n                                                                                                                         : ... In instance DATA_CACHE\n   temp = UpdateData_LRU(DC_LRU, Index);  \n        ^\n%Warning-WIDTH: data/full_repos/permissive/153690221/dropbox/baddam_bourquin_ethakota_finalproject/Source/DataCache.v:295: Operator ASSIGN expects 32 bits on the Assign RHS, but Assign RHS\'s FUNCREF \'UpdateData_LRU\' generates 1 bits.\n                                                                                                                         : ... In instance DATA_CACHE\n   temp = UpdateData_LRU(DC_LRU, Index);  \n        ^\n%Warning-WIDTH: data/full_repos/permissive/153690221/dropbox/baddam_bourquin_ethakota_finalproject/Source/DataCache.v:325: Operator ASSIGN expects 32 bits on the Assign RHS, but Assign RHS\'s FUNCREF \'UpdateData_LRU\' generates 1 bits.\n                                                                                                                         : ... In instance DATA_CACHE\n   temp = UpdateData_LRU(DC_LRU, Index);  \n        ^\n%Warning-WIDTH: data/full_repos/permissive/153690221/dropbox/baddam_bourquin_ethakota_finalproject/Source/DataCache.v:339: Operator ASSIGN expects 3 bits on the Assign RHS, but Assign RHS\'s VARREF \'w\' generates 32 bits.\n                                                                                                                         : ... In instance DATA_CACHE\n     DataLine[DC_TagBits + DC_LRUBits-1 : DC_TagBits] = w;\n                                                      ^\n%Warning-WIDTH: data/full_repos/permissive/153690221/dropbox/baddam_bourquin_ethakota_finalproject/Source/DataCache.v:372: Operator NEQ expects 12 bits on the RHS, but RHS\'s CONST \'8\'h78\' generates 8 bits.\n                                                                                                                         : ... In instance DATA_CACHE\n     if(print == TRUE || MESI_Bits != Invalid || DC_Tag != "x")\n                                                        ^~\n%Warning-WIDTH: data/full_repos/permissive/153690221/dropbox/baddam_bourquin_ethakota_finalproject/Source/DataCache.v:440: Operator ASSIGN expects 9 bits on the Assign RHS, but Assign RHS\'s CONST \'8\'h49\' generates 8 bits.\n                                                                                                                         : ... In instance DATA_CACHE\n   2\'b00: Get_MESI_ID = "I";\n                      ^\n%Warning-WIDTH: data/full_repos/permissive/153690221/dropbox/baddam_bourquin_ethakota_finalproject/Source/DataCache.v:441: Operator ASSIGN expects 9 bits on the Assign RHS, but Assign RHS\'s CONST \'8\'h45\' generates 8 bits.\n                                                                                                                         : ... In instance DATA_CACHE\n   2\'b01: Get_MESI_ID = "E";\n                      ^\n%Warning-WIDTH: data/full_repos/permissive/153690221/dropbox/baddam_bourquin_ethakota_finalproject/Source/DataCache.v:442: Operator ASSIGN expects 9 bits on the Assign RHS, but Assign RHS\'s CONST \'8\'h53\' generates 8 bits.\n                                                                                                                         : ... In instance DATA_CACHE\n   2\'b10: Get_MESI_ID = "S";\n                      ^\n%Warning-WIDTH: data/full_repos/permissive/153690221/dropbox/baddam_bourquin_ethakota_finalproject/Source/DataCache.v:443: Operator ASSIGN expects 9 bits on the Assign RHS, but Assign RHS\'s CONST \'8\'h4d\' generates 8 bits.\n                                                                                                                         : ... In instance DATA_CACHE\n   2\'b11: Get_MESI_ID = "M";\n                      ^\n%Error: Exiting due to 11 warning(s)\n'
module DATA_CACHE(
	input clk,
	input [3:0] command,
	input [`AddressBits-1:0] address,
	input mode,
	output reg [31:0] DC_Read_Hit = 32'b0,
	output reg [31:0] DC_Read_Miss = 32'b0,
	output reg [31:0] DC_Reads = 32'b0,
	output reg [31:0] DC_Write_Hit = 32'b0,
	output reg [31:0] DC_Write_Miss = 32'b0,
	output reg [31:0] DC_Writes = 32'b0
	);
	

	parameter 
		Invalid = 2'b00,
		Exclusive = 2'b01,  
		Shared = 2'b10,
		Modified = 2'b11;


	parameter 
		READ = 4'd0,
		WRITE = 4'd1,

		INVALIDATE = 4'd3,
		SNOOP = 4'd4,
		RESET = 4'd8,
		PRINT = 4'd9;
	  

	parameter 
		DC_IndexBits = $clog2(`DataCacheSet),
		DC_OffsetBits = $clog2(`CacheLineSize),
		DC_TagBits = `AddressBits -(DC_OffsetBits+DC_IndexBits),
		DC_LRUBits = $clog2(`DataCacheWay),  
		MESI_Size = 2;	
	
	reg [DC_TagBits + DC_LRUBits + MESI_Size-1:0] DataCache[0:`DataCacheWay-1][0:`DataCacheSet-1];
	reg [DC_TagBits + DC_LRUBits + MESI_Size-1:0] DataLine;
	
	reg [1:0] MESI_Bits;	
	reg [DC_OffsetBits-1:0] Offset;
	reg [DC_IndexBits-1:0] Index;
	reg [DC_TagBits-1:0] Tag;


	reg [DC_OffsetBits-1:0] DC_Offset;
	reg [DC_IndexBits-1:0] DC_Index;
	reg [DC_TagBits-1:0] DC_Tag;
	reg [DC_LRUBits-1:0] DC_LRU;


	reg [DC_TagBits-1:0] print_Tag [0:`DataCacheWay];
	reg [DC_LRUBits-1:0] print_LRU [0:`DataCacheWay];
	reg [1:0] print_MESI [0:`DataCacheWay];

	parameter TRUE = 1'b1;
	parameter FALSE = 1'b0;

	integer way, found, replaced, w, s, temp;	
	reg print;


	always @(posedge clk)
	begin

		Offset = address[DC_OffsetBits-1:0];
		Index = address[DC_OffsetBits+DC_IndexBits-1:DC_OffsetBits];
		Tag = address[`AddressBits-1:`AddressBits-DC_TagBits];
		

		found=0;
		replaced=0;

		case(command)

		READ:
		begin
			DC_Reads=DC_Reads+1;
			

			for(way=0;way<`DataCacheWay;way=way+1)
			begin		
				DataLine = DataCache[way][Index];
				MESI_Bits = DataLine[DC_TagBits+DC_LRUBits+MESI_Size-1:DC_TagBits+DC_LRUBits];		
				DC_Tag = DataLine[DC_TagBits-1:0];

				if((MESI_Bits != Invalid) && (DC_Tag == Tag))
				begin
					DC_Read_Hit=DC_Read_Hit+1;
					DC_LRU=DataLine[DC_TagBits+DC_LRUBits-1:DC_TagBits];
					
					found=1;

					if (MESI_Bits == Exclusive) 
					begin
						MESI_Bits = Shared;
					end

					DataLine[DC_TagBits+DC_LRUBits+MESI_Size-1:DC_TagBits+DC_LRUBits] = MESI_Bits;
					DataCache[way][Index] = DataLine;	
				end
			end

			if(found==0) 
			begin
				DC_Read_Miss=DC_Read_Miss+1;
				
				if(mode == 1)
					$display("Read from L2 %h", address);


				for(way=0;way<`DataCacheWay;way=way+1)
				begin
					DataLine = DataCache[way][Index];
					MESI_Bits = DataLine[DC_TagBits+DC_LRUBits+MESI_Size-1:DC_TagBits+DC_LRUBits];		

			
					if ((MESI_Bits == Invalid) && (found!=1))
					begin
						found=1;
						
						DC_LRU = DataLine[DC_TagBits+DC_LRUBits-1:DC_TagBits];
						DataLine[DC_TagBits-1:0] = Tag;
						DataLine[DC_TagBits+DC_LRUBits+MESI_Size-1:DC_TagBits+DC_LRUBits] = Exclusive;
						DataCache[way][Index] = DataLine;
					end
				end	

				if(found!=1)
				begin

					for(way=0;way<`DataCacheWay;way=way+1)
					begin
						DataLine = DataCache[way][Index];
						MESI_Bits = DataLine[DC_TagBits+DC_LRUBits+MESI_Size-1:DC_TagBits+DC_LRUBits];		
						DC_LRU = DataLine[DC_TagBits+DC_LRUBits-1:DC_TagBits];
						
						if (DC_LRU == 0 && replaced == 0)
						begin
							replaced = 1;

							if(MESI_Bits == Modified)
							begin
								Offset = 0;
								if(mode == 1)
									$display("Write to L2 %h", {DataLine[DC_TagBits-1:0], Index, Offset});
							end
							
							DC_LRU = DataLine[DC_TagBits+DC_LRUBits-1:DC_TagBits];
							DataLine[DC_TagBits-1:0] = Tag;
							DataLine[DC_TagBits+DC_LRUBits+MESI_Size-1:DC_TagBits+DC_LRUBits] = Exclusive;
							DataCache[way][Index] = DataLine;
						end
					end
					DC_LRU = 0;
				end			
			end
		
			temp = UpdateData_LRU(DC_LRU, Index);	
		end


		WRITE:
		begin
			DC_Writes=DC_Writes+1;

			for(way=0;way<`DataCacheWay;way=way+1)
			begin
				DataLine = DataCache[way][Index];
				MESI_Bits = DataLine[DC_TagBits+DC_LRUBits+MESI_Size-1:DC_TagBits+DC_LRUBits];
				DC_Tag = DataLine[DC_TagBits-1:0];
				
				if((MESI_Bits != Invalid) && (DC_Tag == Tag))
				begin
					DC_Write_Hit=DC_Write_Hit+1;
					DC_LRU = DataLine[DC_TagBits+DC_LRUBits-1:DC_TagBits];
					
					found=1;

					if(MESI_Bits == Shared) 
					begin
						if(mode == 1)
							$display("Write	to L2 %h", address);
						MESI_Bits = Exclusive;
					end
					else if (MESI_Bits == Exclusive) 
					begin
						MESI_Bits = Modified;
					end
					else if (MESI_Bits == Modified) 
					begin
						MESI_Bits = Modified;
					end
					DataLine[DC_TagBits+DC_LRUBits+MESI_Size-1:DC_TagBits+DC_LRUBits] = MESI_Bits;
					DataCache[way][Index] = DataLine;			
				end			
			end

			if(found==0)
			begin
				DC_Write_Miss=DC_Write_Miss+1;
				
				if(mode == 1)
					$display("Read for Ownership from L2 %h", address);


				for(way=0;way<`DataCacheWay;way=way+1)
				begin
					DataLine=DataCache[way][Index];
					MESI_Bits=DataLine[DC_TagBits+DC_LRUBits+MESI_Size-1:DC_TagBits+DC_LRUBits];
			
					if((MESI_Bits == Invalid) && (found!=1))
					begin
						found=1;
						
						DC_LRU = DataLine[DC_TagBits+DC_LRUBits-1:DC_TagBits];
						DataLine[DC_TagBits-1:0] = Tag;
						DataLine[DC_TagBits+DC_LRUBits+MESI_Size-1:DC_TagBits+DC_LRUBits] = Exclusive;
						DataCache[way][Index] = DataLine;


						if(mode == 1)
							$display("Write	to L2 %h ",address);
					end
				end	

				if(found!=1)
				begin
					for(way=0;way<`DataCacheWay;way=way+1)
					begin
						DataLine = DataCache[way][Index];
						MESI_Bits = DataLine[DC_TagBits+DC_LRUBits+MESI_Size-1:DC_TagBits+DC_LRUBits];
						DC_LRU = DataLine[DC_TagBits+DC_LRUBits-1:DC_TagBits];

						if (DC_LRU == 0 && replaced == 0)
						begin
							replaced = 1;

							if(MESI_Bits == Modified)
							begin
								Offset = 0;
								if(mode == 1)
									$display("Write to L2 %h", {DataLine[DC_TagBits-1:0], Index, Offset});
							end
							
							DC_LRU = DataLine[DC_TagBits+DC_LRUBits-1:DC_TagBits];
							DataLine[DC_TagBits-1:0] = Tag;
							DataLine[DC_TagBits+DC_LRUBits+MESI_Size-1:DC_TagBits+DC_LRUBits] = Modified;
							DataCache[way][Index] = DataLine;		
						end
					end
					DC_LRU = 0;
				end
			end	

			temp = UpdateData_LRU(DC_LRU, Index);
		end


		INVALIDATE:
		begin

			for(way=0;way<`DataCacheWay;way=way+1)
			begin				
				DataLine = DataCache[way][Index];
				MESI_Bits = DataLine[DC_TagBits+DC_LRUBits+MESI_Size-1:DC_TagBits+DC_LRUBits];
				DC_Tag = DataLine[DC_TagBits-1:0];

				if(Tag == DC_Tag)
				begin
					MESI_Bits = Invalid;
					DC_LRU = DataLine[DC_TagBits+DC_LRUBits-1:DC_TagBits];
					DataLine[DC_TagBits+DC_LRUBits+MESI_Size-1:DC_TagBits+DC_LRUBits] = MESI_Bits;
					DataLine[DC_TagBits-1:0] = 12'bx;
					DataCache[way][Index] = DataLine;
				end
			end
		
			temp = UpdateData_LRU(DC_LRU, Index);
		end


		SNOOP:
		begin

			for(way=0;way<`DataCacheWay;way=way+1)
			begin
				DataLine = DataCache[way][Index];
				MESI_Bits = DataLine[DC_TagBits+DC_LRUBits+MESI_Size-1:DC_TagBits+DC_LRUBits];
				DC_Tag = DataLine[DC_TagBits-1:0];			
				
				if((MESI_Bits == Modified) && (Tag == DC_Tag))
				begin
					found=1;
					if(mode == 1)
						$display("Return data to L2 %h",address);
				end			
				if(Tag == DC_Tag)
				begin
					found=1;
					MESI_Bits = Invalid;
					DC_LRU = DataLine[DC_TagBits+DC_LRUBits-1:DC_TagBits];
					DataLine[DC_TagBits+DC_LRUBits+MESI_Size-1:DC_TagBits+DC_LRUBits] = MESI_Bits;
					DataLine[DC_TagBits-1:0] = 12'bx;
					DataCache[way][Index] = DataLine;
				end
			end

			temp = UpdateData_LRU(DC_LRU, Index);
		end


		RESET:
		begin
			for (s=0; s<`DataCacheSet; s=s+1)
			begin	
				for (w=0; w<`DataCacheWay; w=w+1)
				begin
					DataLine=DataCache[w][s];

					DataLine[DC_TagBits + DC_LRUBits + MESI_Size-1 : DC_TagBits + DC_LRUBits] = Invalid;

					DataLine[DC_TagBits + DC_LRUBits-1 : DC_TagBits] = w;

					DataLine[DC_TagBits-1:0] = 12'bx;
					DataCache[w][s] = DataLine;
				end
			end
			

			DC_Read_Hit = 32'b0;
			DC_Read_Miss = 32'b0;
			DC_Reads = 32'b0;
			DC_Write_Hit = 32'b0;
			DC_Write_Miss = 32'b0;
			DC_Writes = 32'b0;
		end


		PRINT:
		begin
			$display("__________________________________________________________________");	
			$display("                                                                  ");			
			$display("                        DATA CACHE CONTENTS                       ");
			$display("__________________________________________________________________");
			
			for (s=0;s<`DataCacheSet;s=s+1)
			begin
				print = FALSE;
				for (w=0;w<`DataCacheWay;w=w+1)
				begin
					DataLine = DataCache[w][s];
					MESI_Bits = DataLine[DC_TagBits+DC_LRUBits+MESI_Size-1:DC_TagBits+DC_LRUBits];
					DC_LRU = DataLine[DC_TagBits+DC_LRUBits-1:DC_TagBits];
					DC_Tag = DataLine[DC_TagBits-1:0];
					if(print == TRUE || MESI_Bits != Invalid || DC_Tag != "x")
					begin
						if(print == FALSE)
						begin
							print = TRUE;
							w = -1;
						end
						else
						begin
							print_MESI[w] = MESI_Bits;
							print_LRU[w] = DC_LRU;
							print_Tag[w] = DC_Tag;
						end	
					end
				end			
				if(print == TRUE)
				begin
					$display("Set Index : %h", s);		
					$display("Way:	 1	 2	 3	 4	 5	 6	 7	 8");
					$display("Tag:	%h	%h	%h	%h	%h	%h	%h	%h", print_Tag[0], print_Tag[1], print_Tag[2], print_Tag[3], print_Tag[4], print_Tag[5], print_Tag[6], print_Tag[7]);
					$display("LRU:	%b	%b	%b	%b	%b	%b	%b	%b", print_LRU[0], print_LRU[1], print_LRU[2], print_LRU[3], print_LRU[4], print_LRU[5], print_LRU[6], print_LRU[7]);
					$display("MESI:	%s	%s	%s	%s	%s	%s	%s	%s", Get_MESI_ID(print_MESI[0]), Get_MESI_ID(print_MESI[1]), Get_MESI_ID(print_MESI[2]), Get_MESI_ID(print_MESI[3]), Get_MESI_ID(print_MESI[4]), Get_MESI_ID(print_MESI[5]), Get_MESI_ID(print_MESI[6]), Get_MESI_ID(print_MESI[7]));
					$display("                         ** END OF SET **                         ");
					$display("------------------------------------------------------------------");
				end
			end
			$display("                     END OF DATA CACHE CONTENTS                   ");
			$display("__________________________________________________________________");		
		end

		endcase	
	end
	

	function UpdateData_LRU;
		input [DC_LRUBits-1:0] LRU;
		input [DC_IndexBits-1:0] index;
		
		integer w;

		begin 

			for (w=0; w<`DataCacheWay; w=w+1)
			begin
				DataLine = DataCache[w][index];
				DC_LRU = DataLine[DC_TagBits+DC_LRUBits-1:DC_TagBits];

				if(DC_LRU == LRU)
				begin
					DataLine[DC_TagBits+DC_LRUBits-1:DC_TagBits] = `DataCacheWay-1;
					DataCache[w][index] = DataLine;
				end

				else if(DC_LRU > LRU)
				begin
					DataLine[DC_TagBits+DC_LRUBits-1:DC_TagBits] = DC_LRU-1;
					DataCache[w][index] = DataLine;
				end
			end
		end
	endfunction


	function [8:0] Get_MESI_ID;
		input [1:0] MESI;
		
		begin
			case(MESI)
			2'b00: Get_MESI_ID = "I";
			2'b01: Get_MESI_ID = "E";
			2'b10: Get_MESI_ID = "S";
			2'b11: Get_MESI_ID = "M";
			endcase
		end
	endfunction 

endmodule
module DATA_CACHE(
	input clk,
	input [3:0] command,
	input [`AddressBits-1:0] address,
	input mode,
	output reg [31:0] DC_Read_Hit = 32'b0,
	output reg [31:0] DC_Read_Miss = 32'b0,
	output reg [31:0] DC_Reads = 32'b0,
	output reg [31:0] DC_Write_Hit = 32'b0,
	output reg [31:0] DC_Write_Miss = 32'b0,
	output reg [31:0] DC_Writes = 32'b0
	);

	

	parameter 
		Invalid = 2'b00,
		Exclusive = 2'b01,  
		Shared = 2'b10,
		Modified = 2'b11;


	parameter 
		READ = 4'd0,
		WRITE = 4'd1,

		INVALIDATE = 4'd3,
		SNOOP = 4'd4,
		RESET = 4'd8,
		PRINT = 4'd9;
	  

	parameter 
		DC_IndexBits = $clog2(`DataCacheSet),
		DC_OffsetBits = $clog2(`CacheLineSize),
		DC_TagBits = `AddressBits -(DC_OffsetBits+DC_IndexBits),
		DC_LRUBits = $clog2(`DataCacheWay),  
		MESI_Size = 2;	
	
	reg [DC_TagBits + DC_LRUBits + MESI_Size-1:0] DataCache[0:`DataCacheWay-1][0:`DataCacheSet-1];
	reg [DC_TagBits + DC_LRUBits + MESI_Size-1:0] DataLine;
	
	reg [1:0] MESI_Bits;	
	reg [DC_OffsetBits-1:0] Offset;
	reg [DC_IndexBits-1:0] Index;
	reg [DC_TagBits-1:0] Tag;


	reg [DC_OffsetBits-1:0] DC_Offset;
	reg [DC_IndexBits-1:0] DC_Index;
	reg [DC_TagBits-1:0] DC_Tag;
	reg [DC_LRUBits-1:0] DC_LRU;


	reg [DC_TagBits-1:0] print_Tag [0:`DataCacheWay];
	reg [DC_LRUBits-1:0] print_LRU [0:`DataCacheWay];
	reg [1:0] print_MESI [0:`DataCacheWay];

	parameter TRUE = 1'b1;
	parameter FALSE = 1'b0;

	integer way, found, replaced, w, s, temp;	
	reg print;


	always @(posedge clk)
	begin

		Offset = address[DC_OffsetBits-1:0];
		Index = address[DC_OffsetBits+DC_IndexBits-1:DC_OffsetBits];
		Tag = address[`AddressBits-1:`AddressBits-DC_TagBits];
		

		found=0;
		replaced=0;

		case(command)

		READ:
		begin
			DC_Reads=DC_Reads+1;
			

			for(way=0;way<`DataCacheWay;way=way+1)
			begin		
				DataLine = DataCache[way][Index];
				MESI_Bits = DataLine[DC_TagBits+DC_LRUBits+MESI_Size-1:DC_TagBits+DC_LRUBits];		
				DC_Tag = DataLine[DC_TagBits-1:0];

				if((MESI_Bits != Invalid) && (DC_Tag == Tag))
				begin
					DC_Read_Hit=DC_Read_Hit+1;
					DC_LRU=DataLine[DC_TagBits+DC_LRUBits-1:DC_TagBits];
					
					found=1;

					if (MESI_Bits == Exclusive) 
					begin
						MESI_Bits = Shared;
					end

					DataLine[DC_TagBits+DC_LRUBits+MESI_Size-1:DC_TagBits+DC_LRUBits] = MESI_Bits;
					DataCache[way][Index] = DataLine;	
				end
			end

			if(found==0) 
			begin
				DC_Read_Miss=DC_Read_Miss+1;
				
				if(mode == 1)
					$display("Read from L2 %h", address);


				for(way=0;way<`DataCacheWay;way=way+1)
				begin
					DataLine = DataCache[way][Index];
					MESI_Bits = DataLine[DC_TagBits+DC_LRUBits+MESI_Size-1:DC_TagBits+DC_LRUBits];		

			
					if ((MESI_Bits == Invalid) && (found!=1))
					begin
						found=1;
						
						DC_LRU = DataLine[DC_TagBits+DC_LRUBits-1:DC_TagBits];
						DataLine[DC_TagBits-1:0] = Tag;
						DataLine[DC_TagBits+DC_LRUBits+MESI_Size-1:DC_TagBits+DC_LRUBits] = Exclusive;
						DataCache[way][Index] = DataLine;
					end
				end	

				if(found!=1)
				begin

					for(way=0;way<`DataCacheWay;way=way+1)
					begin
						DataLine = DataCache[way][Index];
						MESI_Bits = DataLine[DC_TagBits+DC_LRUBits+MESI_Size-1:DC_TagBits+DC_LRUBits];		
						DC_LRU = DataLine[DC_TagBits+DC_LRUBits-1:DC_TagBits];
						
						if (DC_LRU == 0 && replaced == 0)
						begin
							replaced = 1;

							if(MESI_Bits == Modified)
							begin
								Offset = 0;
								if(mode == 1)
									$display("Write to L2 %h", {DataLine[DC_TagBits-1:0], Index, Offset});
							end
							
							DC_LRU = DataLine[DC_TagBits+DC_LRUBits-1:DC_TagBits];
							DataLine[DC_TagBits-1:0] = Tag;
							DataLine[DC_TagBits+DC_LRUBits+MESI_Size-1:DC_TagBits+DC_LRUBits] = Exclusive;
							DataCache[way][Index] = DataLine;
						end
					end
					DC_LRU = 0;
				end			
			end
		
			temp = UpdateData_LRU(DC_LRU, Index);	
		end


		WRITE:
		begin
			DC_Writes=DC_Writes+1;

			for(way=0;way<`DataCacheWay;way=way+1)
			begin
				DataLine = DataCache[way][Index];
				MESI_Bits = DataLine[DC_TagBits+DC_LRUBits+MESI_Size-1:DC_TagBits+DC_LRUBits];
				DC_Tag = DataLine[DC_TagBits-1:0];
				
				if((MESI_Bits != Invalid) && (DC_Tag == Tag))
				begin
					DC_Write_Hit=DC_Write_Hit+1;
					DC_LRU = DataLine[DC_TagBits+DC_LRUBits-1:DC_TagBits];
					
					found=1;

					if(MESI_Bits == Shared) 
					begin
						if(mode == 1)
							$display("Write	to L2 %h", address);
						MESI_Bits = Exclusive;
					end
					else if (MESI_Bits == Exclusive) 
					begin
						MESI_Bits = Modified;
					end
					else if (MESI_Bits == Modified) 
					begin
						MESI_Bits = Modified;
					end
					DataLine[DC_TagBits+DC_LRUBits+MESI_Size-1:DC_TagBits+DC_LRUBits] = MESI_Bits;
					DataCache[way][Index] = DataLine;			
				end			
			end

			if(found==0)
			begin
				DC_Write_Miss=DC_Write_Miss+1;
				
				if(mode == 1)
					$display("Read for Ownership from L2 %h", address);


				for(way=0;way<`DataCacheWay;way=way+1)
				begin
					DataLine=DataCache[way][Index];
					MESI_Bits=DataLine[DC_TagBits+DC_LRUBits+MESI_Size-1:DC_TagBits+DC_LRUBits];
			
					if((MESI_Bits == Invalid) && (found!=1))
					begin
						found=1;
						
						DC_LRU = DataLine[DC_TagBits+DC_LRUBits-1:DC_TagBits];
						DataLine[DC_TagBits-1:0] = Tag;
						DataLine[DC_TagBits+DC_LRUBits+MESI_Size-1:DC_TagBits+DC_LRUBits] = Exclusive;
						DataCache[way][Index] = DataLine;


						if(mode == 1)
							$display("Write	to L2 %h ",address);
					end
				end	

				if(found!=1)
				begin
					for(way=0;way<`DataCacheWay;way=way+1)
					begin
						DataLine = DataCache[way][Index];
						MESI_Bits = DataLine[DC_TagBits+DC_LRUBits+MESI_Size-1:DC_TagBits+DC_LRUBits];
						DC_LRU = DataLine[DC_TagBits+DC_LRUBits-1:DC_TagBits];

						if (DC_LRU == 0 && replaced == 0)
						begin
							replaced = 1;

							if(MESI_Bits == Modified)
							begin
								Offset = 0;
								if(mode == 1)
									$display("Write to L2 %h", {DataLine[DC_TagBits-1:0], Index, Offset});
							end
							
							DC_LRU = DataLine[DC_TagBits+DC_LRUBits-1:DC_TagBits];
							DataLine[DC_TagBits-1:0] = Tag;
							DataLine[DC_TagBits+DC_LRUBits+MESI_Size-1:DC_TagBits+DC_LRUBits] = Modified;
							DataCache[way][Index] = DataLine;		
						end
					end
					DC_LRU = 0;
				end
			end	

			temp = UpdateData_LRU(DC_LRU, Index);
		end


		INVALIDATE:
		begin

			for(way=0;way<`DataCacheWay;way=way+1)
			begin				
				DataLine = DataCache[way][Index];
				MESI_Bits = DataLine[DC_TagBits+DC_LRUBits+MESI_Size-1:DC_TagBits+DC_LRUBits];
				DC_Tag = DataLine[DC_TagBits-1:0];

				if(Tag == DC_Tag)
				begin
					MESI_Bits = Invalid;
					DC_LRU = DataLine[DC_TagBits+DC_LRUBits-1:DC_TagBits];
					DataLine[DC_TagBits+DC_LRUBits+MESI_Size-1:DC_TagBits+DC_LRUBits] = MESI_Bits;
					DataLine[DC_TagBits-1:0] = 12'bx;
					DataCache[way][Index] = DataLine;
				end
			end
		
			temp = UpdateData_LRU(DC_LRU, Index);
		end


		SNOOP:
		begin

			for(way=0;way<`DataCacheWay;way=way+1)
			begin
				DataLine = DataCache[way][Index];
				MESI_Bits = DataLine[DC_TagBits+DC_LRUBits+MESI_Size-1:DC_TagBits+DC_LRUBits];
				DC_Tag = DataLine[DC_TagBits-1:0];			
				
				if((MESI_Bits == Modified) && (Tag == DC_Tag))
				begin
					found=1;
					if(mode == 1)
						$display("Return data to L2 %h",address);
				end			
				if(Tag == DC_Tag)
				begin
					found=1;
					MESI_Bits = Invalid;
					DC_LRU = DataLine[DC_TagBits+DC_LRUBits-1:DC_TagBits];
					DataLine[DC_TagBits+DC_LRUBits+MESI_Size-1:DC_TagBits+DC_LRUBits] = MESI_Bits;
					DataLine[DC_TagBits-1:0] = 12'bx;
					DataCache[way][Index] = DataLine;
				end
			end

			temp = UpdateData_LRU(DC_LRU, Index);
		end


		RESET:
		begin
			for (s=0; s<`DataCacheSet; s=s+1)
			begin	
				for (w=0; w<`DataCacheWay; w=w+1)
				begin
					DataLine=DataCache[w][s];

					DataLine[DC_TagBits + DC_LRUBits + MESI_Size-1 : DC_TagBits + DC_LRUBits] = Invalid;

					DataLine[DC_TagBits + DC_LRUBits-1 : DC_TagBits] = w;

					DataLine[DC_TagBits-1:0] = 12'bx;
					DataCache[w][s] = DataLine;
				end
			end
			

			DC_Read_Hit = 32'b0;
			DC_Read_Miss = 32'b0;
			DC_Reads = 32'b0;
			DC_Write_Hit = 32'b0;
			DC_Write_Miss = 32'b0;
			DC_Writes = 32'b0;
		end


		PRINT:
		begin
			$display("__________________________________________________________________");	
			$display("                                                                  ");			
			$display("                        DATA CACHE CONTENTS                       ");
			$display("__________________________________________________________________");
			
			for (s=0;s<`DataCacheSet;s=s+1)
			begin
				print = FALSE;
				for (w=0;w<`DataCacheWay;w=w+1)
				begin
					DataLine = DataCache[w][s];
					MESI_Bits = DataLine[DC_TagBits+DC_LRUBits+MESI_Size-1:DC_TagBits+DC_LRUBits];
					DC_LRU = DataLine[DC_TagBits+DC_LRUBits-1:DC_TagBits];
					DC_Tag = DataLine[DC_TagBits-1:0];
					if(print == TRUE || MESI_Bits != Invalid || DC_Tag != "x")
					begin
						if(print == FALSE)
						begin
							print = TRUE;
							w = -1;
						end
						else
						begin
							print_MESI[w] = MESI_Bits;
							print_LRU[w] = DC_LRU;
							print_Tag[w] = DC_Tag;
						end	
					end
				end			
				if(print == TRUE)
				begin
					$display("Set Index : %h", s);		
					$display("Way:	 1	 2	 3	 4	 5	 6	 7	 8");
					$display("Tag:	%h	%h	%h	%h	%h	%h	%h	%h", print_Tag[0], print_Tag[1], print_Tag[2], print_Tag[3], print_Tag[4], print_Tag[5], print_Tag[6], print_Tag[7]);
					$display("LRU:	%b	%b	%b	%b	%b	%b	%b	%b", print_LRU[0], print_LRU[1], print_LRU[2], print_LRU[3], print_LRU[4], print_LRU[5], print_LRU[6], print_LRU[7]);
					$display("MESI:	%s	%s	%s	%s	%s	%s	%s	%s", Get_MESI_ID(print_MESI[0]), Get_MESI_ID(print_MESI[1]), Get_MESI_ID(print_MESI[2]), Get_MESI_ID(print_MESI[3]), Get_MESI_ID(print_MESI[4]), Get_MESI_ID(print_MESI[5]), Get_MESI_ID(print_MESI[6]), Get_MESI_ID(print_MESI[7]));
					$display("                         ** END OF SET **                         ");
					$display("------------------------------------------------------------------");
				end
			end
			$display("                     END OF DATA CACHE CONTENTS                   ");
			$display("__________________________________________________________________");		
		end

		endcase	
	end
	

	function UpdateData_LRU;
		input [DC_LRUBits-1:0] LRU;
		input [DC_IndexBits-1:0] index;
		
		integer w;

		begin 

			for (w=0; w<`DataCacheWay; w=w+1)
			begin
				DataLine = DataCache[w][index];
				DC_LRU = DataLine[DC_TagBits+DC_LRUBits-1:DC_TagBits];

				if(DC_LRU == LRU)
				begin
					DataLine[DC_TagBits+DC_LRUBits-1:DC_TagBits] = `DataCacheWay-1;
					DataCache[w][index] = DataLine;
				end

				else if(DC_LRU > LRU)
				begin
					DataLine[DC_TagBits+DC_LRUBits-1:DC_TagBits] = DC_LRU-1;
					DataCache[w][index] = DataLine;
				end
			end
		end
	endfunction


	function [8:0] Get_MESI_ID;
		input [1:0] MESI;
		
		begin
			case(MESI)
			2'b00: Get_MESI_ID = "I";
			2'b01: Get_MESI_ID = "E";
			2'b10: Get_MESI_ID = "S";
			2'b11: Get_MESI_ID = "M";
			endcase
		end
	endfunction 

endmodule