forked from libre-chip/cpu
		
	runs instructions that read other instructions' outputs
This commit is contained in:
		
							parent
							
								
									3bd5c77a3f
								
							
						
					
					
						commit
						5b15f4a6b4
					
				
					 4 changed files with 29247 additions and 18604 deletions
				
			
		|  | @ -415,6 +415,16 @@ pub fn reg_alloc(config: &CpuConfig) { | ||||||
|                 .element() |                 .element() | ||||||
|                 .HdlNone(), |                 .HdlNone(), | ||||||
|         ); |         ); | ||||||
|  |         connect( | ||||||
|  |             unit_forwarding_info.unit_reg_frees[unit_index], | ||||||
|  |             HdlOption::map( | ||||||
|  |                 ReadyValid::firing_data(unit_free_regs_tracker.free_in[0]), | ||||||
|  |                 |value| { | ||||||
|  |                     #[hdl] | ||||||
|  |                     UnitOutRegNum::<_> { value } | ||||||
|  |                 }, | ||||||
|  |             ), | ||||||
|  |         ); | ||||||
|         #[hdl] |         #[hdl] | ||||||
|         if let HdlSome(output) = unit_to_reg_alloc.output { |         if let HdlSome(output) = unit_to_reg_alloc.output { | ||||||
|             #[hdl] |             #[hdl] | ||||||
|  |  | ||||||
|  | @ -20,6 +20,7 @@ use std::marker::PhantomData; | ||||||
| #[hdl] | #[hdl] | ||||||
| pub struct UnitForwardingInfo<UnitNumWidth: Size, OutRegNumWidth: Size, UnitCount: Size> { | pub struct UnitForwardingInfo<UnitNumWidth: Size, OutRegNumWidth: Size, UnitCount: Size> { | ||||||
|     pub unit_output_writes: ArrayType<HdlOption<UnitOutputWrite<OutRegNumWidth>>, UnitCount>, |     pub unit_output_writes: ArrayType<HdlOption<UnitOutputWrite<OutRegNumWidth>>, UnitCount>, | ||||||
|  |     pub unit_reg_frees: ArrayType<HdlOption<UnitOutRegNum<OutRegNumWidth>>, UnitCount>, | ||||||
|     pub _phantom: PhantomData<UnitNumWidth>, |     pub _phantom: PhantomData<UnitNumWidth>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -277,7 +278,12 @@ pub fn unit_base< | ||||||
|         HdlOption::is_some(in_flight_ops_summary.empty_op_index), |         HdlOption::is_some(in_flight_ops_summary.empty_op_index), | ||||||
|     ); |     ); | ||||||
| 
 | 
 | ||||||
|     let unit_output_writes = unit_to_reg_alloc.unit_forwarding_info.unit_output_writes; |     #[hdl] | ||||||
|  |     let UnitForwardingInfo::<_, _, _> { | ||||||
|  |         unit_output_writes, | ||||||
|  |         unit_reg_frees, | ||||||
|  |         _phantom: _, | ||||||
|  |     } = unit_to_reg_alloc.unit_forwarding_info; | ||||||
|     #[hdl] |     #[hdl] | ||||||
|     let read_src_regs = wire(mop_ty.src_regs_ty()); |     let read_src_regs = wire(mop_ty.src_regs_ty()); | ||||||
|     connect( |     connect( | ||||||
|  | @ -287,6 +293,26 @@ pub fn unit_base< | ||||||
|     #[hdl] |     #[hdl] | ||||||
|     let read_src_values = wire(); |     let read_src_values = wire(); | ||||||
|     connect(read_src_values, [PRegValue::zeroed(); COMMON_MOP_SRC_LEN]); |     connect(read_src_values, [PRegValue::zeroed(); COMMON_MOP_SRC_LEN]); | ||||||
|  |     #[hdl] | ||||||
|  |     let input_src_regs = wire(mop_ty.src_regs_ty()); | ||||||
|  |     connect( | ||||||
|  |         input_src_regs, | ||||||
|  |         repeat(config.p_reg_num().const_zero().cast_to_bits(), ConstUsize), | ||||||
|  |     ); | ||||||
|  |     #[hdl] | ||||||
|  |     let input_src_regs_valid = wire(); | ||||||
|  |     connect(input_src_regs_valid, [true; COMMON_MOP_SRC_LEN]); | ||||||
|  |     let mut unit_output_regs_valid: Vec<MemBuilder<Bool>> = (0..Expr::ty(unit_output_writes).len()) | ||||||
|  |         .map(|unit_index| { | ||||||
|  |             let mut mem = memory_with_loc( | ||||||
|  |                 &format!("unit_{unit_index}_output_regs_valid"), | ||||||
|  |                 Bool, | ||||||
|  |                 SourceLocation::caller(), | ||||||
|  |             ); | ||||||
|  |             mem.depth(1 << config.out_reg_num_width); | ||||||
|  |             mem | ||||||
|  |         }) | ||||||
|  |         .collect(); | ||||||
|     for unit_index in 0..Expr::ty(unit_output_writes).len() { |     for unit_index in 0..Expr::ty(unit_output_writes).len() { | ||||||
|         let mut unit_output_regs = memory_with_loc( |         let mut unit_output_regs = memory_with_loc( | ||||||
|             &format!("unit_{unit_index}_output_regs"), |             &format!("unit_{unit_index}_output_regs"), | ||||||
|  | @ -308,17 +334,60 @@ pub fn unit_base< | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         for src_index in 0..COMMON_MOP_SRC_LEN { | ||||||
|  |             let read_port = unit_output_regs_valid[unit_index].new_read_port(); | ||||||
|  |             let p_reg_num = input_src_regs[src_index].cast_bits_to(config.p_reg_num()); | ||||||
|  |             connect_any(read_port.addr, p_reg_num.unit_out_reg.value); | ||||||
|  |             connect(read_port.en, false); | ||||||
|  |             connect(read_port.clk, cd.clk); | ||||||
|  |             #[hdl] | ||||||
|  |             if UnitNum::is_index(p_reg_num.unit_num, unit_index) { | ||||||
|  |                 connect(read_port.en, true); | ||||||
|  |                 connect(input_src_regs_valid[src_index], read_port.data); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         let write_port = unit_output_regs.new_write_port(); |         let write_port = unit_output_regs.new_write_port(); | ||||||
|         connect_any(write_port.addr, 0u8); |         connect_any(write_port.addr, 0u8); | ||||||
|         connect(write_port.en, false); |         connect(write_port.en, false); | ||||||
|         connect(write_port.clk, cd.clk); |         connect(write_port.clk, cd.clk); | ||||||
|         connect(write_port.data, PRegValue::zeroed()); |         connect(write_port.data, PRegValue::zeroed()); | ||||||
|         connect(write_port.mask, splat_mask(PRegValue, true.to_expr())); |         connect(write_port.mask, splat_mask(PRegValue, true.to_expr())); | ||||||
|  |         let ready_write_port = unit_output_regs_valid[unit_index].new_write_port(); | ||||||
|  |         connect_any(ready_write_port.addr, 0u8); | ||||||
|  |         connect(ready_write_port.en, false); | ||||||
|  |         connect(ready_write_port.clk, cd.clk); | ||||||
|  |         connect(ready_write_port.data, true); | ||||||
|  |         connect(ready_write_port.mask, true); | ||||||
|         #[hdl] |         #[hdl] | ||||||
|         if let HdlSome(unit_output_write) = unit_output_writes[unit_index] { |         if let HdlSome(unit_output_write) = unit_output_writes[unit_index] { | ||||||
|             connect_any(write_port.addr, unit_output_write.which.value); |             connect_any(write_port.addr, unit_output_write.which.value); | ||||||
|             connect(write_port.data, unit_output_write.value); |             connect(write_port.data, unit_output_write.value); | ||||||
|             connect(write_port.en, true); |             connect(write_port.en, true); | ||||||
|  |             connect_any(ready_write_port.addr, unit_output_write.which.value); | ||||||
|  |             connect(ready_write_port.en, true); | ||||||
|  |             let p_reg_num = #[hdl] | ||||||
|  |             PRegNum::<_, _> { | ||||||
|  |                 unit_num: config.unit_num().from_index(unit_index), | ||||||
|  |                 unit_out_reg: unit_output_write.which, | ||||||
|  |             }; | ||||||
|  |             for src_index in 0..COMMON_MOP_SRC_LEN { | ||||||
|  |                 #[hdl] | ||||||
|  |                 if input_src_regs[src_index].cmp_eq(p_reg_num.cast_to_bits()) { | ||||||
|  |                     connect(input_src_regs_valid[src_index], true); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         let free_write_port = unit_output_regs_valid[unit_index].new_write_port(); | ||||||
|  |         connect_any(free_write_port.addr, 0u8); | ||||||
|  |         connect(free_write_port.en, false); | ||||||
|  |         connect(free_write_port.clk, cd.clk); | ||||||
|  |         connect(free_write_port.data, false); | ||||||
|  |         connect(free_write_port.mask, true); | ||||||
|  |         #[hdl] | ||||||
|  |         if let HdlSome(unit_reg_free) = unit_reg_frees[unit_index] { | ||||||
|  |             connect_any(free_write_port.addr, unit_reg_free.value); | ||||||
|  |             connect(free_write_port.en, true); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -364,16 +433,8 @@ pub fn unit_base< | ||||||
|             SourceLocation::caller(), |             SourceLocation::caller(), | ||||||
|             StaticType::TYPE, |             StaticType::TYPE, | ||||||
|         ); |         ); | ||||||
|         for src_index in 0..COMMON_MOP_SRC_LEN { |         connect(src_ready_flags, input_src_regs_valid); | ||||||
|             connect( |         connect(input_src_regs, input_mop_src_regs); | ||||||
|                 src_ready_flags[src_index], |  | ||||||
|                 config |  | ||||||
|                     .p_reg_num() |  | ||||||
|                     .const_zero() |  | ||||||
|                     .cast_to_bits() |  | ||||||
|                     .cmp_eq(input_mop_src_regs[src_index]), |  | ||||||
|             ); |  | ||||||
|         } |  | ||||||
|         #[hdl] |         #[hdl] | ||||||
|         if unit_to_reg_alloc.cancel_input.cmp_ne(HdlSome( |         if unit_to_reg_alloc.cancel_input.cmp_ne(HdlSome( | ||||||
|             #[hdl] |             #[hdl] | ||||||
|  | @ -494,8 +555,11 @@ pub fn unit_base< | ||||||
|                     #[hdl] |                     #[hdl] | ||||||
|                     if !in_flight_op_canceling[in_flight_op_index] { |                     if !in_flight_op_canceling[in_flight_op_index] { | ||||||
|                         #[hdl] |                         #[hdl] | ||||||
|                         if let InFlightOpState::Running = state { |                         match state { | ||||||
|                             connect(unit_to_reg_alloc.output, HdlSome(unit_output)); |                             InFlightOpState::Running | InFlightOpState::Ready => { | ||||||
|  |                                 connect(unit_to_reg_alloc.output, HdlSome(unit_output)) | ||||||
|  |                             } | ||||||
|  |                             InFlightOpState::CanceledAndRunning => {} | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -47,80 +47,117 @@ fn test_reg_alloc() { | ||||||
|             ), |             ), | ||||||
|         }, |         }, | ||||||
|     ); |     ); | ||||||
|     sim.write( |     let insns = std::array::from_fn::<_, 4, _>(|i| { | ||||||
|         fetch_decode_interface.decoded_insns[0].data, |         MOp.AluBranch(MOp.AluBranch.AddSubI( | ||||||
|         HdlSome( |  | ||||||
|             #[hdl] |             #[hdl] | ||||||
|             FetchedDecodedMOp { |             AddSubMOp { | ||||||
|                 mop: MOp.AluBranch(MOp.AluBranch.AddSub( |                 alu_common: #[hdl] | ||||||
|                     #[hdl] |                 AluCommonMOp { | ||||||
|                     AddSubMOp { |                     common: CommonMOp::new( | ||||||
|                         alu_common: #[hdl] |                         0_hdl_u0, | ||||||
|                         AluCommonMOp { |                         #[hdl] | ||||||
|                             common: CommonMOp::new( |                         MOpDestReg { | ||||||
|                                 0_hdl_u0, |                             normal_regs: #[hdl] | ||||||
|  |                             [ | ||||||
|                                 #[hdl] |                                 #[hdl] | ||||||
|                                 MOpDestReg { |                                 MOpRegNum { value: i as u8 + 1 }, | ||||||
|                                     normal_regs: #[hdl] |                                 MOpRegNum::const_zero(), | ||||||
|                                     [ |                             ], | ||||||
|                                         #[hdl] |                             flag_regs: #[hdl] | ||||||
|                                         MOpRegNum { value: 1u8 }, |                             [HdlSome(()), HdlNone()], | ||||||
|                                         MOpRegNum::const_zero(), |  | ||||||
|                                     ], |  | ||||||
|                                     flag_regs: #[hdl] |  | ||||||
|                                     [HdlSome(()), HdlNone()], |  | ||||||
|                                 }, |  | ||||||
|                                 [2u8, 3u8, 4u8], |  | ||||||
|                                 0x1234.cast_to(SInt[COMMON_MOP_3_IMM_WIDTH]), |  | ||||||
|                             ), |  | ||||||
|                             output_integer_mode: OutputIntegerMode.Full64(), |  | ||||||
|                         }, |                         }, | ||||||
|                         invert_src0: true, |                         [0u8; 2], | ||||||
|                         src1_is_carry_in: true, |                         0x12345678u32.cast_to(SInt[COMMON_MOP_2_IMM_WIDTH]), | ||||||
|                         invert_carry_in: true, |                     ), | ||||||
|                         add_pc: true, |                     output_integer_mode: OutputIntegerMode.DupLow32(), | ||||||
|                     }, |                 }, | ||||||
|                 )), |                 invert_src0: false, | ||||||
|                 is_unrelated_pc: true, |                 src1_is_carry_in: false, | ||||||
|                 pc: 0x1000_hdl_u64, |                 invert_carry_in: false, | ||||||
|  |                 add_pc: false, | ||||||
|             }, |             }, | ||||||
|         ), |         )) | ||||||
|     ); |     }) | ||||||
|     sim.write( |     .into_iter() | ||||||
|         fetch_decode_interface.decoded_insns[1].data, |     .chain( | ||||||
|         HdlSome( |         [ | ||||||
|             #[hdl] |             MOp.AluBranch(MOp.AluBranch.AddSub( | ||||||
|             FetchedDecodedMOp { |                 #[hdl] | ||||||
|                 mop: MOp.AluBranch(MOp.AluBranch.Logical( |                 AddSubMOp { | ||||||
|                     #[hdl] |                     alu_common: #[hdl] | ||||||
|                     LogicalMOp { |                     AluCommonMOp { | ||||||
|                         alu_common: #[hdl] |                         common: CommonMOp::new( | ||||||
|                         AluCommonMOp { |                             0_hdl_u0, | ||||||
|                             common: CommonMOp::new( |                             #[hdl] | ||||||
|                                 0_hdl_u0, |                             MOpDestReg { | ||||||
|                                 #[hdl] |                                 normal_regs: #[hdl] | ||||||
|                                 MOpDestReg { |                                 [ | ||||||
|                                     normal_regs: [ |                                     #[hdl] | ||||||
|                                         #[hdl] |                                     MOpRegNum { value: 1u8 }, | ||||||
|                                         MOpRegNum { value: 2u8 }, |                                     MOpRegNum::const_zero(), | ||||||
|                                         MOpRegNum::const_zero(), |                                 ], | ||||||
|                                     ], |                                 flag_regs: #[hdl] | ||||||
|                                     flag_regs: [HdlNone(), HdlSome(())], |                                 [HdlSome(()), HdlNone()], | ||||||
|                                 }, |                             }, | ||||||
|                                 [3u8, 4u8], |                             [1u8, 0, 0], | ||||||
|                                 SInt[COMMON_MOP_2_IMM_WIDTH].zero(), |                             1.cast_to(SInt[COMMON_MOP_3_IMM_WIDTH]), | ||||||
|                             ), |                         ), | ||||||
|                             output_integer_mode: OutputIntegerMode.Full64(), |                         output_integer_mode: OutputIntegerMode.Full64(), | ||||||
|                         }, |  | ||||||
|                         lut: 0b0110_hdl_u4, |  | ||||||
|                     }, |                     }, | ||||||
|                 )), |                     invert_src0: false, | ||||||
|                 is_unrelated_pc: false, |                     src1_is_carry_in: false, | ||||||
|                 pc: 0x1004_hdl_u64, |                     invert_carry_in: false, | ||||||
|             }, |                     add_pc: false, | ||||||
|         ), |                 }, | ||||||
|  |             )), | ||||||
|  |             MOp.AluBranch(MOp.AluBranch.Logical( | ||||||
|  |                 #[hdl] | ||||||
|  |                 LogicalMOp { | ||||||
|  |                     alu_common: #[hdl] | ||||||
|  |                     AluCommonMOp { | ||||||
|  |                         common: CommonMOp::new( | ||||||
|  |                             0_hdl_u0, | ||||||
|  |                             #[hdl] | ||||||
|  |                             MOpDestReg { | ||||||
|  |                                 normal_regs: [ | ||||||
|  |                                     #[hdl] | ||||||
|  |                                     MOpRegNum { value: 2u8 }, | ||||||
|  |                                     MOpRegNum::const_zero(), | ||||||
|  |                                 ], | ||||||
|  |                                 flag_regs: [HdlNone(), HdlSome(())], | ||||||
|  |                             }, | ||||||
|  |                             [2u8, 4u8], | ||||||
|  |                             SInt[COMMON_MOP_2_IMM_WIDTH].zero(), | ||||||
|  |                         ), | ||||||
|  |                         output_integer_mode: OutputIntegerMode.Full64(), | ||||||
|  |                     }, | ||||||
|  |                     lut: 0b0110_hdl_u4, | ||||||
|  |                 }, | ||||||
|  |             )), | ||||||
|  |         ] | ||||||
|  |         .into_iter() | ||||||
|  |         .cycle(), | ||||||
|     ); |     ); | ||||||
|  |     let mut insn_index = 0; | ||||||
|     for cycle in 0..20 { |     for cycle in 0..20 { | ||||||
|  |         for fetch_index in 0..config.fetch_width.get() { | ||||||
|  |             let mop = insns.clone().nth(insn_index).unwrap(); | ||||||
|  |             sim.write( | ||||||
|  |                 fetch_decode_interface.decoded_insns[fetch_index].data, | ||||||
|  |                 HdlSome( | ||||||
|  |                     #[hdl] | ||||||
|  |                     FetchedDecodedMOp { | ||||||
|  |                         mop, | ||||||
|  |                         is_unrelated_pc: insn_index == 0, | ||||||
|  |                         pc: 0x1000u64 + 4 * insn_index as u64, | ||||||
|  |                     }, | ||||||
|  |                 ), | ||||||
|  |             ); | ||||||
|  |             insn_index += 1; | ||||||
|  |         } | ||||||
|  |         if cycle == 0 { | ||||||
|  |             insn_index = 0; | ||||||
|  |         } | ||||||
|         sim.advance_time(SimDuration::from_nanos(500)); |         sim.advance_time(SimDuration::from_nanos(500)); | ||||||
|         sim.write_clock(sim.io().cd.clk, true); |         sim.write_clock(sim.io().cd.clk, true); | ||||||
|         sim.advance_time(SimDuration::from_nanos(500)); |         sim.advance_time(SimDuration::from_nanos(500)); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue