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() | ||||
|                 .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] | ||||
|         if let HdlSome(output) = unit_to_reg_alloc.output { | ||||
|             #[hdl] | ||||
|  |  | |||
|  | @ -20,6 +20,7 @@ use std::marker::PhantomData; | |||
| #[hdl] | ||||
| pub struct UnitForwardingInfo<UnitNumWidth: Size, OutRegNumWidth: Size, UnitCount: Size> { | ||||
|     pub unit_output_writes: ArrayType<HdlOption<UnitOutputWrite<OutRegNumWidth>>, UnitCount>, | ||||
|     pub unit_reg_frees: ArrayType<HdlOption<UnitOutRegNum<OutRegNumWidth>>, UnitCount>, | ||||
|     pub _phantom: PhantomData<UnitNumWidth>, | ||||
| } | ||||
| 
 | ||||
|  | @ -277,7 +278,12 @@ pub fn unit_base< | |||
|         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] | ||||
|     let read_src_regs = wire(mop_ty.src_regs_ty()); | ||||
|     connect( | ||||
|  | @ -287,6 +293,26 @@ pub fn unit_base< | |||
|     #[hdl] | ||||
|     let read_src_values = wire(); | ||||
|     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() { | ||||
|         let mut unit_output_regs = memory_with_loc( | ||||
|             &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(); | ||||
|         connect_any(write_port.addr, 0u8); | ||||
|         connect(write_port.en, false); | ||||
|         connect(write_port.clk, cd.clk); | ||||
|         connect(write_port.data, PRegValue::zeroed()); | ||||
|         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] | ||||
|         if let HdlSome(unit_output_write) = unit_output_writes[unit_index] { | ||||
|             connect_any(write_port.addr, unit_output_write.which.value); | ||||
|             connect(write_port.data, unit_output_write.value); | ||||
|             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(), | ||||
|             StaticType::TYPE, | ||||
|         ); | ||||
|         for src_index in 0..COMMON_MOP_SRC_LEN { | ||||
|             connect( | ||||
|                 src_ready_flags[src_index], | ||||
|                 config | ||||
|                     .p_reg_num() | ||||
|                     .const_zero() | ||||
|                     .cast_to_bits() | ||||
|                     .cmp_eq(input_mop_src_regs[src_index]), | ||||
|             ); | ||||
|         } | ||||
|         connect(src_ready_flags, input_src_regs_valid); | ||||
|         connect(input_src_regs, input_mop_src_regs); | ||||
|         #[hdl] | ||||
|         if unit_to_reg_alloc.cancel_input.cmp_ne(HdlSome( | ||||
|             #[hdl] | ||||
|  | @ -494,8 +555,11 @@ pub fn unit_base< | |||
|                     #[hdl] | ||||
|                     if !in_flight_op_canceling[in_flight_op_index] { | ||||
|                         #[hdl] | ||||
|                         if let InFlightOpState::Running = state { | ||||
|                             connect(unit_to_reg_alloc.output, HdlSome(unit_output)); | ||||
|                         match state { | ||||
|                             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( | ||||
|         fetch_decode_interface.decoded_insns[0].data, | ||||
|         HdlSome( | ||||
|     let insns = std::array::from_fn::<_, 4, _>(|i| { | ||||
|         MOp.AluBranch(MOp.AluBranch.AddSubI( | ||||
|             #[hdl] | ||||
|             FetchedDecodedMOp { | ||||
|                 mop: MOp.AluBranch(MOp.AluBranch.AddSub( | ||||
|                     #[hdl] | ||||
|                     AddSubMOp { | ||||
|                         alu_common: #[hdl] | ||||
|                         AluCommonMOp { | ||||
|                             common: CommonMOp::new( | ||||
|                                 0_hdl_u0, | ||||
|             AddSubMOp { | ||||
|                 alu_common: #[hdl] | ||||
|                 AluCommonMOp { | ||||
|                     common: CommonMOp::new( | ||||
|                         0_hdl_u0, | ||||
|                         #[hdl] | ||||
|                         MOpDestReg { | ||||
|                             normal_regs: #[hdl] | ||||
|                             [ | ||||
|                                 #[hdl] | ||||
|                                 MOpDestReg { | ||||
|                                     normal_regs: #[hdl] | ||||
|                                     [ | ||||
|                                         #[hdl] | ||||
|                                         MOpRegNum { value: 1u8 }, | ||||
|                                         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(), | ||||
|                                 MOpRegNum { value: i as u8 + 1 }, | ||||
|                                 MOpRegNum::const_zero(), | ||||
|                             ], | ||||
|                             flag_regs: #[hdl] | ||||
|                             [HdlSome(()), HdlNone()], | ||||
|                         }, | ||||
|                         invert_src0: true, | ||||
|                         src1_is_carry_in: true, | ||||
|                         invert_carry_in: true, | ||||
|                         add_pc: true, | ||||
|                     }, | ||||
|                 )), | ||||
|                 is_unrelated_pc: true, | ||||
|                 pc: 0x1000_hdl_u64, | ||||
|                         [0u8; 2], | ||||
|                         0x12345678u32.cast_to(SInt[COMMON_MOP_2_IMM_WIDTH]), | ||||
|                     ), | ||||
|                     output_integer_mode: OutputIntegerMode.DupLow32(), | ||||
|                 }, | ||||
|                 invert_src0: false, | ||||
|                 src1_is_carry_in: false, | ||||
|                 invert_carry_in: false, | ||||
|                 add_pc: false, | ||||
|             }, | ||||
|         ), | ||||
|     ); | ||||
|     sim.write( | ||||
|         fetch_decode_interface.decoded_insns[1].data, | ||||
|         HdlSome( | ||||
|             #[hdl] | ||||
|             FetchedDecodedMOp { | ||||
|                 mop: 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(())], | ||||
|                                 }, | ||||
|                                 [3u8, 4u8], | ||||
|                                 SInt[COMMON_MOP_2_IMM_WIDTH].zero(), | ||||
|                             ), | ||||
|                             output_integer_mode: OutputIntegerMode.Full64(), | ||||
|                         }, | ||||
|                         lut: 0b0110_hdl_u4, | ||||
|         )) | ||||
|     }) | ||||
|     .into_iter() | ||||
|     .chain( | ||||
|         [ | ||||
|             MOp.AluBranch(MOp.AluBranch.AddSub( | ||||
|                 #[hdl] | ||||
|                 AddSubMOp { | ||||
|                     alu_common: #[hdl] | ||||
|                     AluCommonMOp { | ||||
|                         common: CommonMOp::new( | ||||
|                             0_hdl_u0, | ||||
|                             #[hdl] | ||||
|                             MOpDestReg { | ||||
|                                 normal_regs: #[hdl] | ||||
|                                 [ | ||||
|                                     #[hdl] | ||||
|                                     MOpRegNum { value: 1u8 }, | ||||
|                                     MOpRegNum::const_zero(), | ||||
|                                 ], | ||||
|                                 flag_regs: #[hdl] | ||||
|                                 [HdlSome(()), HdlNone()], | ||||
|                             }, | ||||
|                             [1u8, 0, 0], | ||||
|                             1.cast_to(SInt[COMMON_MOP_3_IMM_WIDTH]), | ||||
|                         ), | ||||
|                         output_integer_mode: OutputIntegerMode.Full64(), | ||||
|                     }, | ||||
|                 )), | ||||
|                 is_unrelated_pc: false, | ||||
|                 pc: 0x1004_hdl_u64, | ||||
|             }, | ||||
|         ), | ||||
|                     invert_src0: false, | ||||
|                     src1_is_carry_in: false, | ||||
|                     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 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.write_clock(sim.io().cd.clk, true); | ||||
|         sim.advance_time(SimDuration::from_nanos(500)); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue